1. 程式人生 > 其它 >Mysql基於binlog方式進行資料同步常見問題解決方案彙總

Mysql基於binlog方式進行資料同步常見問題解決方案彙總

0、前置資訊

0.1、叢集資訊

伺服器連線資訊:
10.17.7.1(master)
10.17.7.2(slave1)
10.17.7.3(slave2)
​
使用ssh方式訪問伺服器:
ssh root@10.17.7.*
輸入對應密碼訪問

0.2、從庫資料匯入

在10.17.7.1命令列視窗下直接執行 資料庫表資料匯入:

mysqldump --default-character-set=utf8mb4 --host=10.17.7.1 -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、主庫執行命令

mysql> show master status;

獲取主庫的binlog檔案和當前位置,即查詢結果的 File、Position 欄位,例如:File欄位值為 binlog.XXXXXXXX,Position 欄位值為 YYYYYYYY

1.2、從庫執行命令

mysql> show slave status;
​
mysql> stop slave;
mysql> reset slave;
​
mysql> CHANGE MASTER TO MASTER_HOST = '10.17.7.1', 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.000021

說明:

主庫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'

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 '[email protected]: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為cnki 資訊

mysql> SELECT plugin FROM `mysql`.`user` where user = 'repl';

2> 修改主庫mysql下的 user表中repl對應的mysql_native_password (新舊密碼可以保持一致)

mysql> ALTER USER 'cnki'@'%' 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;

~~~~~~~~~~~~~~~~~~~~~未完待續~~~~~~~~~~~~~~~~~~~