關于MySQL主從複制的過濾,例如通過binlog-ignore-db、replicate-do-db、replicate-wild-do-table等。如果不好好研究過這些過濾選項就用的話,是有可能造成主從資料不一緻問題的。本文将參考MySQL-5.5官方文檔并結合實驗,和各位一起探讨下這裡的各個設定。
以下内容參考5.5官方文檔
binlog_format(STATEMENT,ROW,MIXED,5.5預設為STATEMENT)的設定會導緻一些複制執行上的差異。
當使用MIXED格式時,binlog絕大多數情況也是以STATEMENT格式記錄,隻有在下列情況下才會切換到ROW格式:
1、 當時用UUID()函數時
2、 當一個或多個擁有AUTO_INCREMENT列的表被更新同時有‘trigger’或者‘stored function’被調用時
# MIXED對于‘trigger’和‘stored function’總是使用statement-based
3、 執行INSERT DELAYED時
4、 當視圖裡的某一部分需要row-based複制(例如UUID())時,建立該視圖的語句被改為row-based
5、 使用使用者自定義函數(UDF)時
6、 當某語句被判定為row-based,并且執行它的session需要用到臨時表,則session下的所有子語句都将以ROW格式記錄
7、 當使用USER(),CURRENT_USER()或者 CURRENT_USER
8、 當語句引用了一個或多個system variables。
9、 當使用LOAD_FILE()
所有DDL語句都是基于statements,不論binlog_format如何設定
複制雙方binlog_format需一緻,否則複制無法進行
Binlog格式影響到以下‘複制過濾’配置的行為
--binlog-do-db
--binlog-ignore-db=ljk
該選項的行為取決于binlog格式
Statement-based logging:當use ljk後(即目前庫為ljk時),所有的語句不被記錄進binlog
當登陸mysql後不use/或者use ljk之外的庫,執行update ljk.table 依然會記錄近binlog并複制
Row-based format:告訴伺服器不記錄任何ljk庫下表的更改,無論目前在哪個庫(即無論有無use語句,是否use ljk)
--replicate-do-db = ljk
Statement-based replication:隻有主庫在use ljk 之後執行的語句才會被從庫複制
無use語句或者use其他庫後執行的語句均不被複制
Row-based replication:隻有ljk庫的更改會被複制(無論use哪個庫或者是否use)
無論是否use或use哪個庫,ljk庫之外的變更都不會被複制
--replicate-ignore-db
總結:Statement-based跟目前use的庫有關,Row-based更直接,隻關心指定的庫‘做或不做’。
還有以下兩種參數可‘過濾複制’
以下兩種選項隻對表的更改有影響,庫的複制不受這些參數影響(但是類似ljk.%這種,也會對庫起作用)
--replicate-do-table
這兩個選項在我的實驗裡跟描述不太一緻,詳細見下文實驗結果
--replicate-ignore-table
--replicate-wild-do-table = ljk.%
無論use ljk或use 其他庫或不use,對ljk庫的更新都能被複制,同時,其他庫任何情況下均不會複制(包括建庫建表操作)
--replicate-wild-ignore-table
根據以上,綜合建議:對複制的過濾,采用replicate-wild-do-table/ replicate-wild-ignore-table,比較嚴格和明确
同時,我們先說下根據以上理論以及下面實驗得出的結論:
對于每一個添加的‘複制過濾’配置,應從兩方面考慮
1. 不用use語句引用庫,或者use xxx引用其他庫之後再執行sql(又分兩部分:對‘過濾的庫/表’ 或 ‘對其他庫/表’)會怎樣
2. use xxx引用‘過濾的庫/表’,再執行sql(也分兩部分:對‘過濾的庫/表’ 或 ‘對其他庫/表’)會怎樣
除replicate-wild-do-table=/replicate-wild-ignore-table=外,其他過濾規則會受到“binlog_format”以及“目前所在庫”的影響(即所謂的跨庫問題)
下面是實驗過程(MySQL-5.5.39)
一、 主庫添加“binlog-ignore-db = mysql”,從庫不加過濾
庫操作:
1. 主庫不use,執行建庫語句
mysql> create database kai;
從庫複制
2. 主庫use mysql,再執行
在kai資料庫執行建表操作:
1. 不use
create table kai.li (id int,name char(15));
2. use mysql;
從庫不複制
3. use 其他庫;
對表内容修改:
1. 主庫不use,向li表增加資料
insert into kai.li values('1','ljk');
2. 主庫 use mysql,向li表增加資料
3. 主庫use 其他庫,更新li庫(即跨庫更新)
mysql> use picture;
mysql> insert into kai.li values('2','lhy');
對mysql庫進行更改:
1. 不 use
mysql> create table mysql.ljk (id int,name varchar(15));
2. Use 其他庫
mysql> drop table mysql.ljk;
二、從庫添加“replicate-ignore-db = mysql”,主庫不加過濾
庫操作
在kai資料庫執行建表操作
對mysql庫進行更改
從庫不複制,且從庫狀态正常
3. Use mysql
mysql> create table ljk (id int,name varchar(15));
三、從庫添加“replicate-ignore-table = mysql.%”,主庫不加過濾
注:這條規則加完在任何庫下執行任何語句均複制;相反,在從庫添加replicate-do-table = mysql.%後,在任何庫下執行任何sql都不會被複制。不知道是不是bug
四、 從庫添加“replicate-wild-ignore-table = mysql.%”,主庫不加過濾
實驗也驗證了上文提到的結論。
本文轉自kai404 51CTO部落格,原文連結:<b>http://blog.51cto.com/kaifly/1702679</b>,如需轉載請自行聯系原作者