MySQL 過濾復制+復制映射 配置方法


 

 

場景

node1 和 node2 為兩台不同業務的MySQL服務器。
業務方有個需求,需要將node1上的 employees庫的departments 、dept_manager 這2張表同步到 node2 的 hellodb 庫下面。

這里涉及到3個方面問題,

  1. 版本升級,5.5 -> 5.7
  2. 復制過濾,只復制 departments 、dept_manager 2張表
  3. 重寫庫名,主庫名為 employees ,備庫名為 hellodb

 接下來,我們一步步解決上述的 3 個問題。

 

架構圖1:

 

架構圖2:

 

架構圖3:

 

 

一、版本升級

原主庫版本是 5.5.57,新庫版本是 5.7.21(開啟了gtid,master_auto_position=1)。

 

首先要把新庫的復制改為傳統復制:

# node2 && node3

stop slave;
CHANGE MASTER TO master_auto_position=0;
start slave;

 

然后關掉 GTID:

# node2 && node3

# node2: set global gtid_mode=ON_PERMISSIVE;
# node3: set global gtid_mode=ON_PERMISSIVE;
# node2: set global gtid_mode=OFF_PERMISSIVE;
# node3: set global gtid_mode=OFF_PERMISSIVE;
# node2: set global gtid_mode=OFF; 
# node3: set global gtid_mode=OFF; 
# node2: set global enforce_gtid_consistency=OFF;
# node3: set global enforce_gtid_consistency=OFF;

# 注意 GTID 的在線開啟和關閉,主從需要依次逐步開啟

這樣,5.5 到 5.7 的復制就不會有GTID的硬性問題了(如果你碰到其他不兼容,比如datetime默認值問題,谷歌解決即可)

 

然后把 node1 的employees庫的departments 、dept_manager 這2張表同步到 node3 的 hellodb 庫下面。

# node3

stop slave;
change master to ...

 

附:如何從傳統復制改為基於GTID的復制?

# 開啟 GTID
主從: set global gtid_mode=OFF_PERMISSIVE; 主從: set global gtid_mode=ON_PERMISSIVE; 主從: set global enforce_gtid_consistency=ON; 主從: set global gtid_mode=ON; # 改 auto_increment = 1 stop slave; CHANGE MASTER TO master_auto_position=1; start slave;

 

 

二、復制過濾及重寫庫名

 接下來設置復制過濾,我采用了笨重的重啟方法(5.7 已經支持在線設置復制過濾了),這也是為什么業務遷到 node2,我卻用node3 作為 node1的從庫,因為需要重啟。

修改node3的配置文件:

replicate-rewrite-db = employees -> hellodb
replicate-wild-do-table=hellodb.departments
replicate-wild-do-table=hellodb.dept_manager

注意,如果有 replicate-rewrite-db , replicate-wild-do-table 后面的庫名要寫 rewrite 之后的庫名,而不是原來的庫名。

然后重啟 node3,現在,node1 employees 庫下面的 departments 、dept_manager 表,就會實時同步到 node3和node2 。

node1 -> node3 -> node2

show slave status\G
Replicate_Wild_Do_Table: hellodb.departments,hellodb.dept_manager
Replicate_Rewrite_DB: (employees,hellodb)

 

 

附:在線修改復制過濾

Syntax:
CHANGE REPLICATION FILTER filter[, filter][, ...]

filter:
    REPLICATE_DO_DB = (db_list)
  | REPLICATE_IGNORE_DB = (db_list)
  | REPLICATE_DO_TABLE = (tbl_list)
  | REPLICATE_IGNORE_TABLE = (tbl_list)
  | REPLICATE_WILD_DO_TABLE = (wild_tbl_list)
  | REPLICATE_WILD_IGNORE_TABLE = (wild_tbl_list)
  | REPLICATE_REWRITE_DB = (db_pair_list)

db_list:
    db_name[, db_name][, ...]

tbl_list:
    db_name.table_name[, db_table_name][, ...]
wild_tbl_list:
    'db_pattern.table_pattern'[, 'db_pattern.table_pattern'][, ...]

db_pair_list:
    (db_pair)[, (db_pair)][, ...]

db_pair:
    from_db, to_db

 

# 設置只同步db1,db2這2個庫:(要先停止SQL線程)
使用命令很簡單:CHANGE REPLICATION FILTER REPLICATE_DO_DB = (db1, db2);

# 要是又要全部的庫都要同步該如何操作呢,也很簡單。
STOP SLAVE SQL_THREAD;
CHANGE REPLICATION FILTER REPLICATE_DO_DB = ();
start SLAVE SQL_THREAD;

# 置空多個過濾設置
CHANGE REPLICATION FILTER REPLICATE_REWRITE_DB=(),REPLICATE_WILD_DO_TABLE=(); # 同樣可以可以設置只同步某個庫下面的某張表,或者不同步某個庫下面的某張表。看命令。 mysql> CHANGE REPLICATION FILTER -> REPLICATE_WILD_DO_TABLE = ('db1.t1%'), -> REPLICATE_WILD_IGNORE_TABLE = ('db1.t2%'); # 設置同時同步1個庫下面的某些表可以這樣寫: mysql> CHANGE REPLICATION FILTER -> REPLICATE_WILD_DO_TABLE = ('db2.t1%','db2.t2%');

# 設置重寫DB:(注意需要加2個括號,否則語法報錯,2個括號是因為可以同時設置多對重寫規則)
CHANGE REPLICATION FILTER REPLICATE_REWRITE_DB = ((db_activity,db_webadmin),(db_a,db_b)); 

 

附2:MySQL復制過濾流程

參考官網:https://dev.mysql.com/doc/refman/5.7/en/replication-rules-db-options.html

 

在復制過濾中,有這樣一條規則:

Note:
Only DML statements can be logged using the row format. DDL statements are always logged as statements, even when binlog_format=ROW. All DDL statements are therefore always filtered according to the rules for statement-based replication. This means that you must select the default database explicitly with a USE statement in order for a DDL statement to be applied.

意思是說,DDL語句永遠是以 statement-based 的格式記錄在binlog中的(即使 binlog_format=ROW)。在復制過濾中,要使 DDL 在設置復制過濾的從庫生效,必須顯示指定數據庫(使用 USE db 語句)。

 

由此,小編做了一個測試,A B C 三個實例,B是A的從庫,C是設置了復制過濾的A的從庫。在A執行語句:

ALTER TABLE `db1`.`tb1` DROP INDEX `idx_abc`, ADD INDEX `idx_abc` (`a`,`b`,`c`);

A的binglog如下:
use `test`/*!*/; SET TIMESTAMP=1566374584/*!*/; SET @@session.sql_mode=0/*!*/; /*!\C utf8 *//*!*/; SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=45/*!*/; ALTER TABLE `db1`.`tb1` DROP INDEX `idx_abc`, ADD INDEX `idx_abc` (`a`,`b`,`c`) /*!*/;

可以看到,在未顯示 USE db 的情況下,MySQL使用了默認的test庫。結果是:B節點正確復制了該語句,C節點卻沒有。在C的error log中找到如下錯誤信息:

2019-08-21T16:03:04.376974+08:00 144172 [Note] Slave SQL for channel '': Worker 1 failed executing transaction 'ANONYMOUS' at master log mysql-bin.616178, end_log_pos 31881792; 
Could not execute Query event. Detailed error: Slave SQL thread ignored the query because of replicate-*-table rules; Error log throttle is enabled. 
This error will not be displayed for next 60 secs. It will be suppressed, Error_code: 1237

 

(一)對於 Database-Level Replication,MySQL的處理流程如下:

1. Which logging format is used?

  • STATEMENT. Test the default database.
  • ROW. Test the database affected by the changes.

 

2. Are there any --replicate-do-db options?

  • Yes. Does the database match any of them?
    •   Yes. Continue to Step 4.
    •   No. Ignore the update and exit.
  • No. Continue to step 3.

 

3.  Are there any --replicate-ignore-db options?

  • Yes. Does the database match any of them?
    •   Yes. Ignore the update and exit.
    •   No. Continue to step 4.
  • No. Continue to step 4.

 

4. Proceed to checking the table-level replication options, if there are any. For a description of how these options are checked, see Section 16.2.5.2, “Evaluation of Table-Level Replication Options”.

 

(二)對於 Table-Level Replication,MySQL的處理流程如下:

 

1. Are there any table replication options?

  • Yes. Continue to step 2.
  • No. Execute the update and exit.

 

2. Which logging format is used?

  • STATEMENT. Carry out the remaining steps for each statement that performs an update.
  • ROW. Carry out the remaining steps for each update of a table row.

 

3. Are there any --replicate-do-table options?

  • Yes. Does the table match any of them?
    •   Yes. Execute the update and exit.
    •   No. Continue to step 4.
  • No. Continue to step 4.

 

4. Are there any --replicate-ignore-table options?

  • Yes. Does the table match any of them?
    •   Yes. Ignore the update and exit.
    •   No. Continue to step 5.
  • No. Continue to step 5.

 

5. Are there any --replicate-wild-do-table options?

  • Yes. Does the table match any of them?
    •   Yes. Execute the update and exit.
    •   No. Continue to step 6.
  • No. Continue to step 6.

 

6. Are there any --replicate-wild-ignore-table options?

  • Yes. Does the table match any of them?
    •   Yes. Ignore the update and exit.
    •   No. Continue to step 7.
  • No. Continue to step 7.

 

7. Is there another table to be tested?

  • Yes. Go back to step 3.
  • No. Continue to step 8.

 

8. Are there any --replicate-do-table or --replicate-wild-do-table options?

  • Yes. Ignore the update and exit.
  • No. Execute the update and exit.

 

注意:如果一張表同時被設置了  --replicate-do-table and --replicate-wild-do-table option, 或 --replicate-ignore-table and --replicate-wild-ignore-table ,那么只有 binlog_format=ROW 的 DML 語句可以被復制到從庫。

 


免責聲明!

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



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