1. 程式人生 > >MySQL主從複製常遇到的幾個坑

MySQL主從複製常遇到的幾個坑

主從複製架構圖如下:


主庫有資料變更時,會通知備庫的io執行緒,io執行緒建立一個TCP長連線,接下來主庫的binlog dump執行緒會推送主庫的binlog。在進行完一次HTTP操作後保持該TCP連線(HTTP/1.1起預設使用長連線)。只要Server端或Client端不提出關閉請求,或存在其他異常情況,兩者間的連線將持續下去。

主庫的worker執行緒在寫binlog的時候是併發工作的,而主庫的dump執行緒和從庫的IO執行緒在讀和收binlog的過程中是單執行緒工作的(5.7版本之後支援多執行緒)。因此高併發的情況下,從庫很有可能跟不上主庫的進度(非同步複製)。

主從同步環境下,由於主備庫搭建複製關係時,備庫“不乾淨”,導致有可能遇到備庫無法執行某個binlog event的情況,此時在確定binlog中該event的影響之後,可以採用:1)在從庫上 set sql_log_bin=OFF;  [建立缺失的記錄;]  set sql_log_bin=ON;  2)pt-slave-restart 跳過N個錯誤:--skip-count=N、跳過指定錯誤碼:--error-numbers=1062;  3)set global sql_slave_skip_counter=N;跳過N個binlog event。

特別需要指出的是:set global sql_slave_skip_counter,當第N個event存在於某個事務,則該event所在的整個事務也將被跳過。

我們在互動介面內輸入的一句SQL,表現在binlog中的記錄就有所不同了。

如下截取了一段row格式記錄的binlog:

# at 8982883
#170803 16:35:08 server id 23712  end_log_pos 8982951 	Query	thread_id=1601	exec_time=0	error_code=0
SET TIMESTAMP=1501749308/*!*/;
BEGIN
/*!*/;
# at 8982951
# at 8983010
#170803 16:35:08 server id 23712  end_log_pos 8983010 	Table_map: `demo`.`heartbeat` mapped to number 35
#170803 16:35:08 server id 23712  end_log_pos 8983156 	Update_rows: table id 35 flags: STMT_END_F


BINLOG '
POCCWROgXAAAOwAAAOIRiQAAACMAAAAAAAEABGRlbW8ACWhlYXJ0YmVhdAAGDwMPCA8IBmgA/AP8
Azw=
POCCWRigXAAAkgAAAHQSiQAAACMAAAAAAAEABv//8BoyMDE3LTA4LTAzVDE2OjM1OjA3LjAwMTQw
MKBcAAAQAG15c3FsLWJpbi4wMDAwMzE3EIkAAAAAAPAaMjAxNy0wOC0wM1QxNjozNTowOC4wMDE2
MjCgXAAAEABteXNxbC1iaW4uMDAwMDMxYxGJAAAAAAA=
'/*!*/;
# at 8983156
#170803 16:35:08 server id 23712  end_log_pos 8983183 	Xid = 158813
COMMIT/*!*/;

再看一段relay log中的binlog event group


mysql> show relaylog events in "mysql-relay-bin.000051" from 5867832 limit 5 \G
*************************** 1. row ***************************
   Log_name: mysql-relay-bin.000051
        Pos: 5867832
 Event_type: Query
  Server_id: 23712
End_log_pos: 10170351
       Info: BEGIN
*************************** 2. row *************************** Log_name: mysql-relay-bin.000051 Pos: 5867900 Event_type: Table_map Server_id: 23712 End_log_pos: 10170410 Info: table_id: 35 (demo.heartbeat) *************************** 3. row *************************** Log_name: mysql-relay-bin.000051 Pos: 5867959 Event_type: Update_rows Server_id: 23712 End_log_pos: 10170556 Info: table_id: 35 flags: STMT_END_F *************************** 4. row *************************** Log_name: mysql-relay-bin.000051 Pos: 5868105 Event_type: Xid Server_id: 23712 End_log_pos: 10170583 Info: COMMIT /* xid=179683 */ *************************** 5. row *************************** Log_name: mysql-relay-bin.000051 Pos: 5868132 Event_type: Query Server_id: 23712 End_log_pos: 10170651 Info: BEGIN 5 rows in set (0.00 sec)

可以看到對heartbeat表的一次update操作,對應binlog中記錄有如下4條event:

1、BEGIN

2、Table_map

3、Update_rows

4、COMMIT

主從複製過濾引數優先考慮:replicate-wild-ignore-table

主庫的max_allowed_packet需要小於等於備庫的max_allowed_packet。

否則當binlog為ROW格式,本來資料量就大,此時又有大事務在主庫執行完之後,容易出現無法傳輸到備庫執行的情況。

提示:Slave_IO_Running: No

Got a packet bigger than 'max_allowed_packet' bytes

啟用帶加密連線的主從複製

https://dev.mysql.com/doc/refman/5.5/en/replication-solutions-secure-connections.html