MySQL 5.5主從關於‘復制過濾’的深入探究


關於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()

 

下面幾點要注意

1.所有DDL語句都是基於statements,不論binlog_format如何設置

2.復制雙方binlog_format需一致,否則復制無法進行

3.Binlog格式影響到以下‘復制過濾’配置的行為

 

--binlog-do-db
--binlog-ignore-db=ljk     #黑名單,這個庫的修改不記錄二進制日志。
該選項的行為取決於binlog格式
對於Statement-based logging:當use ljk后(即當前庫為ljk時),所有的語句不被記錄進binlog
當登陸mysql后不使用use或者use ljk之外的庫,執行update ljk.table 依然會記錄近binlog並復制[只對ljk庫生效]
對於Row-based format:告訴服務器不記錄任何ljk庫下表的更改,無論當前在哪個庫(即無論有無use語句,是否使用use  ljk)

 

--replicate-do-db = ljk             #白名單,允許復制哪個庫
該選項的行為取決於binlog格式
對於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,比較嚴格和明確

下面是實驗過程(MySQL-5.5.39)
一、 主庫添加“binlog-ignore-db = mysql”,從庫不加過濾

 

庫操作:
    1. 主庫不use,執行建庫語句
    mysql> create database kai;
    從庫復制
    2. 主庫use  mysql,再執行
    mysql> create database kai;
    從庫復制

在kai數據庫執行建表操作:
    1. 沒有use
    create table kai.li (id int,name char(15));
    從庫復制
    2. use mysql;
    create table kai.li (id int,name char(15));
    從庫不復制
    3. use 其他庫;
    create table kai.li (id int,name char(15));
    從庫復制

對表內容修改:
    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;
    從庫復制

 總結:對於主庫使用binlog-ignore-db來說:只有在use db執行后才會生效

二、從庫添加“replicate-ignore-db = mysql”,主庫不加過濾

 

庫操作
    1. 主庫不use,執行建庫語句
    mysql> create database kai;
    從庫復制
    2. 主庫use  mysql,再執行
    mysql> create database kai;
    從庫復制

在kai數據庫執行建表操作
    1. 沒有使用use
    create table kai.li (id int,name char(15));
    從庫復制
    2. use mysql;
    create table kai.li (id int,name char(15));
    從庫不復制
    3. use 其他庫;
    create table kai.li (id int,name char(15));
    從庫復制

對表內容修改:
    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;
    從庫復制
    3. Use mysql
    mysql> create table ljk (id int,name varchar(15));
    從庫不復制

 總結對於從庫設定replicate-ignore-db 來說,基本上只有在主庫使用use db時才會生效。

三、從庫添加“replicate-ignore-table = mysql.%”,主庫不加過濾

 

注:這條規則加完在任何庫下執行任何語句均復制;相反,在從庫添加replicate-do-table = mysql.%后,在任何庫下執行任何sql都不會被復制。不知道是不是bug

庫操作:
    1. 主庫不use,執行建庫語句
    mysql> create database kai;
    從庫復制
    2. 主庫use  mysql,再執行    
    mysql> create database kai;
    從庫復制

在kai數據庫執行建表操作
    1. 不use
    create table kai.li (id int,name char(15));
    從庫復制
    2. use mysql;
    create table kai.li (id int,name char(15));
    從庫復制   ????
    3. use 其他庫;
    create table kai.li (id int,name char(15));
    從庫復制

對表內容修改:
    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;
    從庫復制
    3. Use mysql
    mysql> create table ljk (id int,name varchar(15));
    從庫復制

 總結:好像有bug,應該來說在use db后,並在對應的庫下創建表應該會忽略同步。

四、 從庫添加“replicate-wild-ignore-table = mysql.%”,主庫不加過濾

 

庫操作:
    1. 主庫不use,執行建庫語句
    mysql> create database kai;
    從庫復制
    2. 主庫use  mysql,再執行
    mysql> create database kai;
    從庫復制

在kai數據庫執行建表操作
    1. 不use
    create table kai.li (id int,name char(15));
    從庫復制
    2. use mysql;
    create table kai.li (id int,name char(15));
    從庫復制
    3. use 其他庫;
    create table kai.li (id int,name char(15));
    從庫復制

對表內容修改:
    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;
    從庫不復制
    3. Use mysql
    mysql> create table ljk (id int,name varchar(15));
    從庫不復制

 總結:使用replicate-wild-ignore-table之后,所有對於mysql庫下的表級別的任何操作都被忽略同步

綜上參考官方文檔以及實驗,可得出結論:

對於每一個添加的‘復制過濾’配置,應從兩方面考慮:

    1. 不用use語句引用庫,或者use xxx引用其他庫之后再執行sql(又分兩部分:對‘過濾的庫/表’ 或 ‘對其他庫/表’)會怎樣

    2. use xxx引用‘過濾的庫/表’,再執行sql(也分兩部分:對‘過濾的庫/表’ 或 ‘對其他庫/表’)會怎樣

除replicate-wild-do-table=/replicate-wild-ignore-table=外,其他過濾規則會受到“binlog_format”以及“當前所在庫”的影響(即所謂的跨庫問題)

 

 

建議使用
replicate-wild-ignore-table=mysql.%
因為replicate-ignore-db 是通過use db來確定是否過濾的。
而wild-ignore是通過真實被修改的表進行過濾的,更為准確。

實驗也驗證了上文提到的“對復制的過濾,采用replicate-wild-do-table/ replicate-wild-ignore-table,比較嚴格和明確

本文永久更新鏈接地址http://www.linuxidc.com/Linux/2015-10/124181.htm


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM