MySQL配置主从复制

初始环境

有一台机器A安装了MySQL5.7.20作为主数据库服务器,它已经运行了一段时间,具有小规模的数据。一个Web应用使用Spring+JPA+Hibernate来访问这个数据库。

目标

在机器B上安装MySQL作为slave数据库服务器,与主数据库形成主从复制架构。修改Web应用使读写分离,所有读操作走slave数据库,所有写操作走master数据库。

步骤

1.安装备库

在机器B上安装MySQL5.7.20。参考官方文档https://dev.mysql.com/doc/refman/5.7/en/linux-installation-rpm.html

2.创建复制账号

在主库上创建一个用户,并赋予合适的权限。备库将用这个用户连接到主库并读取其二进制日志。

mysql> grant replication slave,replication client on *.* to repl identified by 'Welcome1';

3. 配置主库和备库

在主库上打开二进制日志,并指定一个唯一的服务器ID。在主库的my.cnf文件中增加或修改如下内容:

server-id               = 43(服务器id,每台机器要唯一,最好用IP最后一位)
log_bin                 = mysql-bin(这是主服务器,必须开启log_bin,这句就是开启了)
binlog_format           = mixed(混合比较好,还有statements,rows)
binlog_do_db            = master(需要同步的数据库,如果多个数据库,重复这个配置)
binlog_ignore_db        = mysql(排除不需要同步的数据库,如果多个数据库,重复这个配置)
expire_logs_days        = 7(二进制日志自动删除或过期的天数。默认为0,不删除)
slave_skip_errors       = 1062 (跳过指定的错误,1062指主键重复,1032是主从数据库不一致, 请百度更多)
binlog_cache_size       = 1M (为每个session分配的内存)

查看二进制日志文件是否已经在主库上建立。

mysql> show master status;
Empty set (0.00 sec)

说明二进制日志文件还没有建立。需要重启MySQL服务,

sh-4.1# /sbin/service mysqld restart
Stopping mysqld:                                           [  OK  ]
Starting mysqld:                                           [  OK  ]

再次查看,发现二进制日志文件已经建立。

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

备库也需要在my.cnf中增加类似的配置,然后也需要重启MySQL服务。

log_bin=mysql-bin
server_id=45
relay_log=/var/lib/mysql/mysql-relay-bin
log_slave_updates=1 (表示slave将复制事件写进自己的二进制日志)
read_only=1 (表示从节点只能读,不能写)

4. 启动复制

我们要告诉备库如何连接到主库并重放其二进制日志。

mysql> change master to master_host='host1',
    -> master_user='repl',
    -> master_password='Welcome1',
    -> master_log_file='mysql-bin.000001',
    -> master_log_pos=0;

Query OK, 0 rows affected, 2 warnings (0.04 sec)

master_log_pos设置为0,说明要从日志开头读起。然后可以使用show slave status来检查复制是否正确执行。

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: slc05ida.us.oracle.com
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 4
               Relay_Log_File: mysql-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: No
              ......
        Seconds_Behind_Master: NULL
              ......
1 row in set (0.00 sec)

发现Slave_IO_State,Slave_IO_Running和Slave_SQL_Running三列显示当前备库复制还没开始运行。而且日志开头是4,不是0。

运行下面的命令开始执行复制:

mysql> start slave;

Query OK, 0 rows affected (0.00 sec)

再次查看

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: slc05ida.us.oracle.com
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 367
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
           ......
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           ......

1 row in set (0.01 sec)

在主库上执行show processlist\G可以看到复制线程。

mysql> show processlist\G
*************************** 5. row ***************************
     Id: 9
   User: repl
   Host: slc10giz.us.oracle.com:40508
     db: NULL
Command: Binlog Dump
   Time: 93
  State: Master has sent all binlog to slave; waiting for more updates
   Info: NULL

5 rows in set (0.00 sec)

在备库上执行show processlist\G可以看到一个I/O线程和一个SQL线程。

mysql> show processlist\G
*************************** 1. row ***************************
     Id: 4
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: starting
   Info: show processlist
*************************** 2. row ***************************
     Id: 5
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 152
  State: Waiting for master to send event
   Info: NULL
*************************** 3. row ***************************
     Id: 6
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 151
  State: Slave has read all relay log; waiting for more updates
   Info: NULL
3 rows in set (0.00 sec)

5. 从主库克隆数据

配置了上面的主从复制之后,我们发现备库没有获得主库原有的数据。因为以上的主从复制只是同步配置主从复制之后发生的事件。我们需要用其他方法克隆主库原来的数据。这里我们使用mysqldump。它只是用于数据库中只有InnoDB表的时候。

-bash-4.1$ /usr/bin/mysqldump --single-transaction --all-databases --master-data=1 --host=host1 -ufmwhatool -pfmwhatool| mysql --host=host2 -uroot -pWelcome1
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 3021 (HY000) at line 22: This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first.
mysqldump: Got errno 32 on write

看来我们需要先把主从复制关掉。

mysql> stop slave;
Query OK, 0 rows affected (0.03 sec)
-bash-4.1$ /usr/bin/mysqldump --single-transaction --all-databases --master-data=1 --host=1 -ufmwhatool -pfmwhatool| mysql --host=host2 -uroot -pWelcome1
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.

这次没有报错。

过了一会儿,我们查看备库,发现数据已经克隆过去了。

再用start slave;命令打开主从复制。

在主库中某个Table里插入记录,就会发现从库里的这个Table里马上就有这条记录了。

OK,到此主从复制成功。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章