需求
公司內部有幾十套基於傳統複製的MySQL主從實例,並且binlog的格式都是STATEMENT格式。在接手這些MySQL主從實例以後就有考慮過想將binlog格式更改爲ROW格式。而此次則是由於咱們elk上面一個第三方工具須要解析和監聽binlog信息,而且只能解析ROW格式的binlog,藉此機會正好將公司部分MySQL主從複製實例的binlog格式更改爲ROW格式。ide
ROW和STATEMENT比對
- row格式
- 優勢:就是可以徹底保證主從數據的一致性,不會出現由於在SQL中使用MySQL自帶的函數致使數據不一致的現象。例如:當使用now()函數的時候,可能由於從庫延時的問題致使時間的數據不一致。線上是有遇到過這個問題的。
- 缺點:就是會消耗比較大的磁盤空間和磁盤IO;還有一個比較重要的問題就是由於ROW格式是基於每行進行修改的,如果在master執行一個update修改5000行數據,那麼slave就會執行5000次修改數據操做,那麼這就會帶來更嚴重的主從延遲。(由於咱們線上使用的是MySQL5.6,是基於schema的並行複製,而且slave的硬件資源是比master差的)
- statement格式
- 優勢:就是消耗較少的磁盤存儲和IO。
- 缺點:可能會致使數據不一致,而且在作基於binlog恢復的時候可能會出現數據不一致的現象。
binlog格式變動的難點
雖然binlog變動是能夠進行在線修改的,可是因爲MySQL的master上面存在許多的長連接,哪怕你動態修改以後,長連接的寫入和修改仍是舊的binlog格式。在這裏最開始有提出過倆個方案:函數
- 重啓master。可是線上業務沒法中斷,因此沒法進行修改。
- kill掉全部的長連接。可是因爲長連接太多,一個個去kill掉的話實在是耗費時間和經歷,因此也不被承認。
解決方案
最後仍是迴歸到需求自己,關於咱們的需求就是須要解析binlog的格式是ROW格式,因此咱們最後的方案就是在slave上面修改binlog的格式爲ROW格式。(log_slave_updates參數必須在slave上面打開。不然master經過binlog傳遞到slave上面重放的SQL是不會在slave本地的binlog記錄的)工具
- 可是須要注意的是修改完畢以後要想在slave上面的須要重啓啓動複製。即stop slave,start slave。不然是不會生效的。
- 還有一個須要注意的是,當slave上面已經修改爲了ROW格式的時候,這個時候在將slave的binlog格式修改爲STATEMENT格式的話,複製是會報錯的,哪怕從新restart slave 也會報錯。