MySQL 5.5主從關於‘複製過濾’的深刻探究

關於MySQL主從複製的過濾,例如經過binlog-ignore-db、replicate-do-db、replicate-wild-do-table等。若是很差好研究過這些過濾選項就用的話,是有可能形成主從數據不一致問題的。本文將參考MySQL-5.5官方文檔並結合實驗,和各位一塊兒探討下這裏的各個設置。mysql

    如下內容參考5.5官方文檔linux

binlog_format的設置會致使一些複製執行上的差別。sql

格式有三種(STATEMENT,ROW,MIXED,5.5默認爲STATEMENT)數據庫

當使用MIXED格式時,binlog絕大多數狀況也是以STATEMENT格式記錄,只有在下列狀況下才會切換到ROW格式:服務器

一、 當時用UUID()函數時session

二、 當一個或多個擁有AUTO_INCREMENT列的表被更新同時有‘trigger’或者‘stored function’被調用時函數

  # MIXED對於‘trigger’和‘stored function’老是使用statement-basedpost

三、 執行INSERT DELAYED時spa

四、 當視圖裏的某一部分須要row-based複製(例如UUID())時,建立該視圖的語句被改成row-based日誌

五、 使用用戶自定義函數(UDF)時

六、 當某語句被斷定爲row-based,而且執行它的session須要用到臨時表,則session下的全部子語句都將以ROW格式記錄

七、 當使用USER(),CURRENT_USER()或者 CURRENT_USER

八、 當語句引用了一個或多個system variables。

九、 當使用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)
1、 主庫添加「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執行後纔會生效

2、從庫添加「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時纔會生效。

3、從庫添加「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後,並在對應的庫下建立表應該會忽略同步。

4、 從庫添加「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

相關文章
相關標籤/搜索