Press "Enter" to skip to content

Day: September 26, 2017

MySQL的主从同步

MySQL从3.23版本开始提供复制的功能。复制是指将主数据库的DDL和DML操作通过二进制日志传到从数据库上,然后在从库上对这些日志redo,从而使得从库和主库的数据保持同步。


概述

  1. 主库在commit时把数据变更作为events记录在binlog中;
  2. 主库推送binlog到从库的relay_log,之后从库从relay_log执行redo,通过逻辑复制以达到主从数据一致。

MySQL通过三个线程来完成主从复制:
1. binlog dump线程在主库上运行,将数据操作推送给从库;
2. I/O线程跑在从库上,将binlog日志中的事件更新到relay_log中;
3. SQL线程跑在从库上,将relay_log中更新的数据库事件应用到从库。

架构

复制的常见架构有:
1. 一主多从复制,适用于读压力大,实现读写分离;
2. 多级复制架构,主要为了解决主库的I/O负载和网络压力,但延迟大;
3. 双主复制架构,适用于主从切换;


搭建

主库

操作系统为ubuntu,域名beijing.sujx.net,关闭ufw,开启vsftpd;

$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf 

server-id = 100
log_bin                 = /var/log/mysql/mysql-bin.log
bind-address            = 192.168.122.106

$ sudo systemctl restart mysql 
$ mysql -u root -p 
mysql> grant replication slave on *.* to replica@'%' identified by 'password'; 
mysql> flush privileges; 
mysql> flush tables with read lock; 

mysql> show master status\G
*************************** 1. row ***************************
File: **mysql-bin.000012**
Position: **1677**
Binlog_Do_DB: 
Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)
mysql> exit
mysqldump -uroot -p --all-databases --lock-all-tables --events > mysql_dump.sql
lftp sujx@shanghai.sujx.net
put mysql_dump.sql
$ mysql -u root -p 
mysql> unlock tables;

从库

操作系统为ubuntu,域名shanghai.sujx.net,关闭ufw,开启vsftpd;

$ mysql -u root -p < /tmp/mysql_dump.sql 
$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

server-id = 101
read_only=1
report-host=beijing.sujx.net

$sudo systemctl restart mysql 
$ mysql -u root -p 
mysql> change master to
-> master_host='beijing.sujx.net',
-> master_user='replica',
-> master_password='password',
-> master_log_file='mysql-bin.000012',
-> master_log_pos=1677;
mysql> SET GLOBAL sql_slave_skip_counter = 1;
mysql> start slave;
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: beijing.sujx.net
                  Master_User: replica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000012
          Read_Master_Log_Pos: 1677
               Relay_Log_File: shanghai-relay-bin.000020
                Relay_Log_Pos: 1202
        Relay_Master_Log_File: mysql-bin.000012
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1007
                   Last_Error: Error 'Can't create database 'sujx'; database exists' on query. Default database: 'sujx'. Query: 'create database sujx'
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 989
              Relay_Log_Space: 2147
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 1007
               Last_SQL_Error: Error 'Can't create database 'sujx'; database exists' on query. Default database: 'sujx'. Query: 'create database sujx'
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 100
                  Master_UUID: d84bbcff-a41f-11e7-a7e7-525400537531
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: 
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 170929 17:39:55
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

测试

在主库上面进行删库、建库、导入数据即可。

Tips

Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
这个问题是因为mysql目录中的auto.conf中的UUID值相同,修改之后就可以正常。

Last_IO_Errno: 1045 Last_IO_Error: error connecting to master ‘replication@
这个问题是change master语句错误

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

IO和SQL线程显示正常却无法复制数据时,需要设置SET GLOBAL sql_slave_skip_counter Syntax跳过内部出错的地方。