由於歷史遺留問題,我們的MySQL主從庫的表結構不一致,主庫的某個表tableA比從庫表tableA少了一個欄位。
當嘗試在主庫上更改表結構時,這行alter語句會隨著binlog同步到從庫,如果從庫執行這行語句時出錯,主從同步執行緒就會自動停止,那樣只能人為手動處理錯誤,然後再啟動slave上的主從同步執行緒。場景大概是下面這個樣子:
1,在主庫上執行alter table aaa add column xxx int default 1 after yyy;
2,從庫同時也會執行這樣語句,但是由於從庫上已經有xxx這個欄位了,於是主從執行緒更改表失敗,這個時候用show slave status檢視主從狀態就會發現類似於下面這樣的語句:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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: 1060 Last_Error: Error 'Duplicate column name ' xxx '' on query. Default database: 'dbxxx' . Query: 'alter table aaa add column xxx int default 1 after yyy' //此處省略了一些語句 Last_SQL_Errno: 1060 Last_SQL_Error: Error 'Duplicate column name ' xxx '' on query. Default database: 'dbxxx' . Query: 'alter table aaa add column xxx int default 1 after yyy' |
可以看到,從主庫複製binlog的salve_io執行緒還在忙活,但是執行從庫更新的slave_sql已經罷工了,從Last_error:可以看到是因為執行主庫中國來的alter table aaa add column xxx int default 1 after yyy時出錯了,具體原因是這個表上已經有了xxx這一列。
手動的解決方法是告訴從庫slave_sql執行緒讓他忽略掉這個錯誤繼續執行:
1
2
|
mysql>set global sql_slave_skip_counter=1; mysql>start slave; |
上面的語句是告訴slave跳過當前卡住的event,然後重新起來幹活。
上面的方法在slave比較少的時候還可以,但是當從庫有幾十臺時,逐臺去處理既費時又容易出錯,怎樣在主庫這一側一勞永逸地避免呢?
對,就是在主庫這側不要將這樣alter這樣語句寫入到binlog中,MySQL不愧世界級的軟體產品,它提供了一個session粒度的選項,通過關閉這個選項可以不讓主庫將開啟這個選項或關閉連線前的SQL語句寫入binlog。
1
2
|
mysql>set sql_log_bin=off; mysql>alter table aaa add column xxx int default 1 after yyy; |