type
status
date
slug
summary
tags
category
icon
password
語法
filter 類型
REPLICATE_DO_DB、REPLICATE_IGNORE_DB
要求 SQL THREAD 執行或忽略來自 Source 針對該 DB 的語法。
確切的效果取決於 binlog_format:
- statement:依照語句的默認 database (即 USE database) 來進行判斷,如果默認 database 不包含在此 filter 或者沒有 USE database 則不會執行該語句。
- row:依照語句實際異動的 database 來決定。
設定前請務必參照章節: MySQL 如何評估過濾規則 了解細節。
另外添加在設定檔
my.cnf
或是 command line 中指定時,若要指定多個 DB 請多次使用此選項,因為一次只能設定一個 DB,不能使用 ,
分隔是因為名稱中可能包含 ,
。REPLICATE_DO_TABLE、REPLICATE_IGNORE_TABLE
要求 SQL THREAD 執行或忽略來自 Source 針對該 TABLE 的語法。
另外添加在設定檔
my.cnf
或是 command line 中指定時,若要指定多個 TABLE 請多次使用此選項,因為一次只能設定一個 DB,不能使用 ,
分隔是因為名稱中可能包含 ,
。REPLICATE_WILD_DO_TABLE、REPLICATE_WILD_IGNORE_TABLE
告訴 SQL THREAD 當有來自 source 的 table 異動,符合這裡設定的 table 名稱模板時,則需要執行或忽略語句。此處和 LIKE 匹配相同,允許
%
和 _
通配符。當 replicate_wild_do_table = foo%.bar%,則 SQL THREAD 會執行 database 名稱為 foo 開頭,並且 table 名稱為 bar 開頭的 table 更新。
當 replicate_wild_do_table = foo%.% 像這樣 table 匹配為 %,則 SQL THREAD 會執行 foo 開頭的 database 的 database-level 語句 (CREATE DATABASE, DROP DATABASE, ALTER DATABASE)。
當 DB 或 TABLE 名稱中包含通配符,需要使用
\
進行轉譯,假設要複製前綴為 my_own
的 TABLE,則需要如下設置:REPLICATE_REWRITE_DB
此選項需要指定 2 個DB,假設設定為 from_ → dbB,則會將來自 source 中對 dbA database 的操作映射到 replica 中的 dbB database。
只有涉及 TABLE 的語句才會受此選項影像,DB 層級的語句不受影響,例如:CREATE DATABASE、DROP DATABASE、ALTER DATABASE ......等。
此設定優先於其他的 filter 設定,會先應用
REPLICATE_REWRITE_DB
之後才會檢查其他 filter。確切的效果取決於 binlog_format:
- statement:依照語句的默認 database (即 USE database) 來進行判斷。
- row:依照語句實際異動的 database 來決定。
因此為了確保 rewrite 結果符合預期,尤其是和其他 filter 合併使用,建議參照以下事項:
- 在 source 和 replica 中需要手動建立這 2 個 database
- 如果 binlog_format 是 statement 或 mix 的話,不論是 DDL 或 DML 語句都避免跨 database 查詢,也不要在語句中指定 database 名稱,確保在執行語法前正確的 USE database
- 如果 binlog_format 是 row 的話,請確保執行 DDL 語句前指定 database 名稱,並避免在語句中指定 database。DML 語句則不受影響。
一些細節
- 需要
REPLICATION_SLAVE_ADMIN
或SUPER
權限
- 使用此語句設定 replication filter 之前需要
STOP REPLICA SQL_THREAD
停止 sql 線程,設定完畢後再使用START REPLICA SQL_THREAD
開始應用。
- 若該語句未添加
FOR CHANNEL
指定 replication channel,則視為 global 設定應用於所有 channel。
- MySQL 從 8.0 開始才支援
FOR CHANNEL
語句來為每個CHANNEL
設置不同的 Filter。在 8.0 之前只能 global 設定,如需使用可能需要搭配blackhole
engine + statement 格式的 binlog 來達到效果。
- GROUP REPLICATION 無法進行設定,因為這樣會導致 GROUP 內所有成員沒有資料一致。
- 執行語句時有指定的 filter 會直接覆蓋原本的設定,沒有指定的 filter 則是維持原有的值。
- 如果在同一個語句中多次指定同一個 filter 則最後一個生效,例如以下 2 個語句最後
DO_DB
都會是db3
和db4
:
- 若要取消 filter 設置,針對 filter 提供空列表即可,如下:
- TABLE-LEVEL 的 filter 只有當 SQL 語句中明確提及操作的 TABLE 才適用,例如:雖然 GRANT 語句會更新 mysql.user 表,但因為語句沒有指定 TABLE 因此不會被 table-level 的 filter 影響。
持久化 (my.cnf 設定)
使用
CHANGE REPLICATION FILTER
並不會持久化設定,重新啟動 server 會直接重置掉,因此若要持久化可以將設定寫入 my.cnf
,以下列出寫入 my.cnf
的注意事項:- 需指定 channel 時,請使用
channel_name:db_name.table_name
的方式指定,如下:
- 如果要指定多個 DB 或 TABLE 需要列出多次,如下:
因為 MySQL 會將第一個
:
(channel 使用) 以外的其他字元都視為名稱的一部分,在上述錯誤範例中 MySQL 會將 database1,database2
視為 DB 名稱,因此不會執行 database1
和 database2
的語法。- 使用
replicate_wild_%
類型的 filter,如果 DB 或 TABLE 名稱中包含通配符,需要使用\
進行轉譯,假設要複製前綴為my_own
的 TABLE,則需要如下設置:
因為
_
在 wild 中視為通配符-表示一個字元,因此上述錯誤的設置中不止會複製 my_own
開頭的表,還會複製 myAown
、 myBown
......等名稱前綴的表,所以需要加上 \
來將 _
轉譯。MySQL 如何評估過濾規則
replicate-rewrite-db 會優先應用於所有 replicate-* 的規則。
Database-Level 的判定步驟
- 語句在 binlog 是用什麼 format 紀錄?
- STATEMENT:檢查預設的 database (USE database)。
- ROW:檢查是哪個 database 受到影響。
- 是否有任何 REPLICATE_DO_DB 的選項?
- YES:是否有任何符合的 database?
- YES:跳到步驟4。
- NO:忽略此語句並退出。
- NO:繼續下一個步驟3。
- 是否有任何 REPLICATE_IGNORE_DB 的選項?
- YES:是否有任何符合的 database?
- YES:忽略此語句並退出。
- NO:繼續下一個步驟4。
- NO:繼續下一個步驟4。
- 繼續檢查 Table-Level 的規則
DDL 語句無論如何都是用 STATEMENT 格式紀錄,所以在使用 DDL 語句前必須 USE database 才能在 filter 這邊做符合期望的判斷。
STATEMENT 格式有一個例外是 CREATE DATABASE,ALTER DATABASE 和 DRP DATABASE,在執行這些操作之前預設 database 會自動切換成對象 DATABASES。
使用 routine (SP、function) 時,會隱式的 USE routine 所在的 DATABASE (routine 結束後會撤銷),並且在 routine 內不能使用 USE DATABASE 語句,因此如果 routine 內包含 DDL 語句,會以 routine 所在 DATABASE 做判斷,需要特別注意。
Table-Level 的判定步驟
除非沒有 Database-Level 的 filter 選項,否則會先優先判斷 Database-Level 隨後才是 Table-Level。
- 是否有任何 Table-Level 的 replication filter 選項?
- YES:繼續下一個步驟2。
- NO:執行此語句並退出。
- 語句在 binlog 是用什麼 format 紀錄?
- STATEMENT:對每一個 statement 執行後續步驟。
- ROW:對每一個 ROW 的更新執行後續步驟。
當 binlog format = Statement 時,replication event 就是單句 SQL 語法。
當 binlog format = ROW 時,replication event 則是對每一個 ROW 的異動。
若是以 replication event 的角度來看,在 Table-Level 的判定過程都是相同的
- 是否有任何 REPLICATE_DO_TABLE 選項?
- YES:是否有任何符合的 Table?
- YES:執行此語句並退出。
- NO:繼續下一個步驟4。
- NO:繼續下一個步驟4。
- 是否有任何 REPLICATE_IGNORE_TABLE 選項?
- YES:是否有任何符合的 Table?
- YES:忽略此語句並退出。
- NO:繼續下一個步驟5。
- NO:繼續下一個步驟5。
- 是否有任何 REPLICATE_WILD_DO_TABLE 選項?
- YES:是否有任何符合的 Table?
- YES:執行此語句並退出。
- NO:繼續下一個步驟6。
- NO:繼續下一個步驟6。
- 是否有任何 REPLICATE_WILD_IGNORE_TABLE 選項?
- YES:是否有任何符合的 Table?
- YES:忽略此語句並退出。
- NO:繼續下一個步驟7。
- NO:繼續下一個步驟7。
- 是否還有其他 TABLE 要測試?
- YES:回到步驟3。
- NO:繼續下一個步驟8。
- 是否有任何 REPLICATE_DO_TABLE 或 REPLICATE_WILD_DO_TABLE 選項?
- YES:忽略此語句並退出。
- NO:執行此語句並退出。
當語句同時涉及兩張表,其中一個表符合 DO 條件,另一個表符合 IGNORE 條件時,則:
當 binlog format = Statement 時,會導致 replication 中斷。
當 binlog format = Row 時,更新符合 DO 條件的表,並忽略更新符合 IGNORE 條件的表。
使用 replication filter 的建議
經過知道上述的判定方式,可以了解到當同時使用 Database-Level 和 Table-Level 的 filter 時,有時候會出現一些違反直覺的情況,並且 binlog format 也會影響到 filter 的判定方式,如下範例:
在 slave 上設定如下 filter:
在 master 上執行如下語法:
當 binlog format = ROW 時,slave 會執行如下語法:
當 binlog format = STATEMENT 時,slave 不會執行任何語法,因為默認的 database 是 db1,所以會被 replicate-ignore-db 給過濾掉。
因此當使用 replication filter 的時候可以遵循以下方式:
- 當需要同時使用 Database-Level 和 Table-Level 的 filter,則建議遵循其中一個策略:
- 當 binlog format = ROW 時,在執行 DDL 語句前必須先使用 USE 語句指定預設 database。
- 當 binlog format = STATEMENT 時,不論是執行 DDL 還是 DML 語句,都必須先使用 USE 語句指定預設 database。
- 避免使用 Database-Level 的 filter,僅使用 Table-Level 的 filter,且 DML 語句不同時更新多表。
- 為了能夠簡單確認設置的結果,建議避免同時使用 do、ignore 選項。