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 的語法。
REPLICATE_%_DB 不一樣,不會受 binlog_format 影響,會依照實際異動的 TABLE 決定,設定前請務必參照章節: MySQL 如何評估過濾規則 了解細節。
另外添加在設定檔 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_ADMINSUPER 權限
  • 使用此語句設定 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 都會是 db3db4
    • 若要取消 filter 設置,針對 filter 提供空列表即可,如下:
      • TABLE-LEVEL 的 filter 只有當 SQL 語句中明確提及操作的 TABLE 才適用,例如:雖然 GRANT 語句會更新 mysql.user 表,但因為語句沒有指定 TABLE 因此不會被 table-level 的 filter 影響。

      持久化 (my.cnf 設定)

      使用 CHANGE REPLICATION FILTER 並不會持久化設定,重新啟動 server 會直接重置掉,因此若要持久化可以將設定寫入 my.cnf,以下列出寫入 my.cnf 的注意事項:
      1. 需指定 channel 時,請使用 channel_name:db_name.table_name 的方式指定,如下:
        1. 如果要指定多個 DB 或 TABLE 需要列出多次,如下:
          1. 因為 MySQL 會將第一個 : (channel 使用) 以外的其他字元都視為名稱的一部分,在上述錯誤範例中 MySQL 會將 database1,database2 視為 DB 名稱,因此不會執行 database1database2 的語法。
        1. 使用 replicate_wild_% 類型的 filter,如果 DB 或 TABLE 名稱中包含通配符,需要使用 \ 進行轉譯,假設要複製前綴為 my_own 的 TABLE,則需要如下設置:
          1. 因為 _ 在 wild 中視為通配符-表示一個字元,因此上述錯誤的設置中不止會複製 my_own 開頭的表,還會複製 myAownmyBown ......等名稱前綴的表,所以需要加上 \ 來將 _ 轉譯。

        MySQL 如何評估過濾規則

        replicate-rewrite-db 會優先應用於所有 replicate-* 的規則。

        Database-Level 的判定步驟

        1. 語句在 binlog 是用什麼 format 紀錄?
            • STATEMENT:檢查預設的 database (USE database)。
            • ROW:檢查是哪個 database 受到影響。
        1. 是否有任何 REPLICATE_DO_DB 的選項?
            • YES:是否有任何符合的 database?
              • YES:跳到步驟4。
              • NO:忽略此語句並退出。
            • NO:繼續下一個步驟3。
        1. 是否有任何 REPLICATE_IGNORE_DB 的選項?
            • YES:是否有任何符合的 database?
              • YES:忽略此語句並退出。
              • NO:繼續下一個步驟4。
            • NO:繼續下一個步驟4。
        1. 繼續檢查 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。
        1. 是否有任何 Table-Level 的 replication filter 選項?
            • YES:繼續下一個步驟2。
            • NO:執行此語句並退出。
        1. 語句在 binlog 是用什麼 format 紀錄?
            • STATEMENT:對每一個 statement 執行後續步驟。
            • ROW:對每一個 ROW 的更新執行後續步驟。
            💡
            當 binlog format = Statement 時,replication event 就是單句 SQL 語法。 當 binlog format = ROW 時,replication event 則是對每一個 ROW 的異動。 若是以 replication event 的角度來看,在 Table-Level 的判定過程都是相同的
        1. 是否有任何 REPLICATE_DO_TABLE 選項?
            • YES:是否有任何符合的 Table?
              • YES:執行此語句並退出。
              • NO:繼續下一個步驟4。
            • NO:繼續下一個步驟4。
        1. 是否有任何 REPLICATE_IGNORE_TABLE 選項?
            • YES:是否有任何符合的 Table?
              • YES:忽略此語句並退出。
              • NO:繼續下一個步驟5。
            • NO:繼續下一個步驟5。
        1. 是否有任何 REPLICATE_WILD_DO_TABLE 選項?
            • YES:是否有任何符合的 Table?
              • YES:執行此語句並退出。
              • NO:繼續下一個步驟6。
            • NO:繼續下一個步驟6。
        1. 是否有任何 REPLICATE_WILD_IGNORE_TABLE 選項?
            • YES:是否有任何符合的 Table?
              • YES:忽略此語句並退出。
              • NO:繼續下一個步驟7。
            • NO:繼續下一個步驟7。
        1. 是否還有其他 TABLE 要測試?
            • YES:回到步驟3。
            • NO:繼續下一個步驟8。
        1. 是否有任何 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 選項。

        參考