Mysql基於binlog方式進行數據同步常見問題解決方案匯總
0、前置信息
0.1、集群信息
服務器連接信息: 192.168.91.131(master) 192.168.91.132(slave1) 192.168.91.133(slave2) 使用ssh方式訪問服務器: ssh root@192.168.91.* 輸入對應密碼訪問
0.2、從庫數據導入
192.168.91.13
mysqldump --default-character-set=utf8mb4 --host=192.168.91.131 -uroot -p123456 --opt --set-gtid-purged=OFF 從庫需要導入數據的數據庫名 | mysql --host=從庫IP地址 --port=3306 -uroot -p123456 --default-character-set=utf8mb4 -C 從庫需要導入數據的數據庫名
說明: 使用此方式進行數據導入時,保證目標數據庫中數據表與源數據庫中數據表一致,同時,目標數據庫中數據表保證為空表
0.3 、從庫設置同步過濾規則
---- 從庫設置同步過濾規則(在my.cnf中設置,對應k8s在配置字典中配置) ---- replicate_wild_do_table = 要同步的數據庫名.%
replicate_wild_ignore_table = 要忽略的數據庫名.%
1、數據同步(binlog方式)
主、從庫使用binlog方式同步數據,操作步驟:
1.1、主、從庫修改數據庫配置
1> 修改mysql配置文件
vi /etc/my.cnf
添加如下內容:
# 服務編號(與其它節點不沖突即可) server_id=1 log_bin=binlog binlog_format=ROW
systemctl restart mysqld.service
1.2、主庫操作說明
mysql> CREATE USER repl IDENTIFIED BY '123456'; mysql> GRANT SELECT, SHOW VIEW, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'%'; mysql> FLUSH PRIVILEGES;
2> 獲取主庫的binlog文件和當前位置
mysql> show master status;
獲取主庫的binlog文件和當前位置,即查詢結果的 File、Position 字段,例如:File字段值為 binlog.XXXXXXXX,Position 字段值為 YYYYYYYY
1.3、從庫關聯同步主庫數據
mysql> CHANGE MASTER TO MASTER_HOST = '192.168.91.131', MASTER_USER = 'repl', MASTER_PASSWORD = '123456', MASTER_PORT = 3306, MASTER_LOG_FILE='binlog.XXXXXXXX', MASTER_LOG_POS=YYYYYYYY; mysql> start slave; mysql> show slave status;
2、常見問題匯總及解決
2.1、主、從庫數據表字符集不一致
2.1.1、報錯信息
Last_SQL_Errno: 1677
Last_SQL_Error: Column 1 of table 'XXX' cannot be converted from type 'varchar(150(bytes))' to type 'varchar(110(bytes))'
2.1.2、解決方案
1> 主、從庫查看數據表的字符集信息
mysql> show create table 表名;
2> 從庫執行如下命令
mysql> stop slave; mysql> alter table table_name convert to character set 主庫數據表字符集; mysql> start slave;
mysql> show slave status;
2.2、主庫刪除從庫不存在數據
2.2.1、報錯信息
Last_Errno: 1032
Last_SQL_Error: Could not execute Delete_rows event on table XXX; Can't find record in 'XXX', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND;
2.2.2、解決方案
1> 在從庫執行如下命令:
mysql> show slave status;
找到Exec_Master_Log_Pos的值,例如:XXXX;Last_Error信息中的end_log_pos的值,例如:YYYYYY
2> 在主庫使用自帶的mysqlbinlog查看刪除信息:
cd /usr/bin
mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS --start-position=XXXX --stop-position=YYYYYY /var/lib/mysql/binlog.000001
說明:
主庫mysqlbinlog所在文件夾位置,可以使用如下命令查找:
whereis mysqlbinlog
3> 找到刪除語句之后,在從庫插入刪除數據,例如:
insert into test values(1, 'jack');
4> 在從庫執行如下命令
mysql> start slave;
mysql> show slave status;
插入數據時,如果遇到索引沖突的問題,可參考如下操作:
mysql插入數據時,出現Duplicate entry 'XXX' for key 'XXX'的問題: 可以使用replace into, replace into是insert into的增強版: (1) 如果插入的數據不重復,執行的是insert into操作,影響1條記錄 (2) 如果插入的數據重復,執行的是update操作,影響2條記錄:先刪除舊的數據,再插入新的數據。 示例: replace into test values(1,'jack')
mysql> show slave status\G;
mysql> show binlog events IN 'binlog.000021' FROM XXXX limit 10;
找到XXXX對應的SESSION.GTID_NEXT值,例如:ZZZZZ
3> 在從庫中執行如下語句
mysql> stop slave; mysql> set GTID_NEXT='ZZZZZ'; mysql> begin;commit; mysql> set GTID_NEXT='AUTOMATIC'; mysql> start slave; mysql> show slave status;
mysql> show master status;
(2)在從庫中執行如下語句
mysql> stop slave; mysql> reset master; mysql> set global gtid_purged='2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-19345623'; mysql> start slave; mysql> show slave status;
2.3、主庫更新從庫不存在數據
2.3.1、報錯信息
Last_Errno: 1032
Last_Error: Could not execute Update_rows event on table XXX; Can't find record in 'XXXX', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log binlog.0000XX, end_log_pos XXXXX
2.3.2、解決方案
1> 在從庫執行如下命令:
mysql> show slave status; # 也可使用: mysql> show slave status\G;
找到Exec_Master_Log_Pos的值,例如:XXXX;Last_Error信息中的end_log_pos的值,例如:YYYYYY
2> 在主庫使用mysqlbinlog查看更新操作的數據:
mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS --start-position=XXXX --stop-position=YYYYYY /var/lib/mysql/binlog.000001
3> 在主庫中查看更新之后的數據,然后將這些數據導出;並在從庫執行插入語句插入數據。
4> 在主庫中查詢執行事件:
mysql> show binlog events IN 'binlog.000001' FROM XXXX limit 50;
找到XXXX對應的SESSION.GTID_NEXT值 ZZZZZ
5> 在從庫中執行如下語句
mysql> stop slave; mysql> set GTID_NEXT='ZZZZZ'; mysql> begin;commit; mysql> set GTID_NEXT='AUTOMATIC'; mysql> start slave; mysql> show slave status;
2.4、從庫連接數不足導致同步失敗
2.4.1、報錯信息
Slave_IO_State: connecting to master Last_IO_Error: MySql Host is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
2.4.2、解決方案
1> 主、從數據庫都要查看max_connection_errors
(1) 進入主、從庫Mysql數據庫查看max_connection_errors
mysql> show variables like '%max_connect_errors%';
(2) 修改max_connection_errors的數量為1000
mysql> set global max_connect_errors = 1000;
(3) 查看是否修改成功
mysql> show variables like '%max_connect_errors%';
2> 在主、從庫下清理一下hosts文件
mysql> flush hosts;
2.5、主庫下caching_sha2_password插件導致連接異常
2.5.1、報錯信息
Last_IO_Error: error connecting to master 'repl@192.168.91.131:3306' - retry-time: 60 retries: 7 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
2.5.2、解決方案
1> 在主庫下數據庫名為 mysql下的 user表,查看 user為repl 信息
mysql> SELECT plugin FROM `mysql`.`user` where user = 'repl';
2> 修改主庫mysql下的 user表中repl對應的mysql_native_password (新舊密碼可以保持一致)
mysql> ALTER USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
2.6、主從數據同步報錯1782
2.6.1、報錯信息
Last_Errno: 1782 Last_Error: Error executing row event: '@@SESSION.GTID_NEXT cannot be set to ANONYMOUS when @@GLOBAL.GTID_MODE = ON.'
2.6.2、解決方案
在從庫中執行如下命令:
mysql> stop slave sql_thread; mysql> set GLOBAL GTID_MODE = ON_PERMISSIVE; mysql> set GLOBAL GTID_MODE = OFF_PERMISSIVE; mysql> set GLOBAL GTID_MODE = OFF; mysql> start slave sql_thread; mysql> start slave; mysql> show slave status;
2.7、主從數據同步報錯1781
2.7.1、報錯信息
Last_Errno: 1781 Last_Error: @@SESSION.GTID_NEXT cannot be set to UUID:NUMBER when @@GLOBAL.GTID_MODE = OFF.
2.7.2、解決方案
在從庫中執行如下命令:
mysql> set GLOBAL GTID_MODE = OFF_PERMISSIVE; mysql> set GLOBAL GTID_MODE = ON_PERMISSIVE; mysql> set GLOBAL GTID_MODE = ON; mysql> start slave; mysql> show slave status;
2.8、從庫存在數據,主庫插入相同數據同步失敗
說明:
此種情況是從庫存在數據,導致主庫在插入相同數據時,從庫數據同步報錯。
2.8.1、報錯信息
Last_Errno: 1062 Last_Error: Could not execute Write_rows event on table XXXX.xxx; Duplicate entry 'XXX' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log binlog.XXXXXXX, end_log_pos XXXXXXX
2.8.2、解決方案
針對此種情況,保證以主庫數據為主,同時刪除從庫數據時需要考慮從庫表數據主鍵是否為自增。
mysql> stop slave; mysql> delete from XXXX.xxx where 主鍵字段='XXX'; mysql> start slave; mysql> show slave status;
2.9、中繼日志損壞
2.9.1、報錯信息
Last_SQL_Error: Error initializing relay log position: I/O error reading the header from the binary log Last_SQL_Error: Error initializing relay log position: Binlog has bad magic number; It's not a binary log file that can be used by this version of MySQL
2.9.2、解決方案
說明:找到同步的binlog和POS點,然后重新做同步,這樣就可以有新的中繼日志
1> 在從庫查找執行的中繼日志Relay_Master_Log_File和Exec_Master_Log_Pos節點
mysql> show slave status\G;
獲取 Relay_Master_Log_File 值(例如:binlog.xxxxx) 和 Exec_Master_Log_Pos 值(例如:YYYYYY)
2> 在從庫執行如下命令
mysql> stop slave; mysql> CHANGE MASTER TO MASTER_LOG_FILE='binlog.xxxxx', MASTER_LOG_POS=YYYYYY; mysql> start slave; mysql> show slave status\G;
~~~~~~~~~~~~~~~~~~~~~未完待續~~~~~~~~~~~~~~~~~~~