mysql 複製原理與實踐

weixin_34391854發表於2018-12-28

複製功能是將一個mysql資料庫上的資料復到一個或多個mysql從資料庫上。

複製的原理:在主伺服器上執行的所有DDL和DML語句都會被記錄到二進位制日誌中,這些日誌由連線到它的從伺服器獲取,並複製到從庫,並儲存為中繼日誌,

這個過程由一個稱為 IO執行緒 的執行緒負責,還有一個稱為 SQL執行緒 的則按順序執行中繼日誌中的語句。

 

複製有多種拓撲形式:

1、傳統複製,一主多從,一個主伺服器多個從伺服器。

2、鏈式複製,一臺伺服器從主庫複製,而另一臺伺服器又從這臺複製,中間伺服器又叫中繼主庫。

3、主主複製,兩個主庫互相接受寫入和複製。

4、多源複製,一個從庫,從多個主庫複製。

 

一、複製如何操作

1、在主庫上啟用二進位制日誌記錄。

2、在主庫上建立一個複製使用者。

3、在從訓上設定唯一的 server_id。

4、從主庫中備份資料。

5、在從庫上恢復主庫備份的資料。

6、執行CHANGE MASTER TO命令。

7、開始複製。

 

二、具體的操作步驟如下:
1、在 主庫 上,啟用二進位制日誌並設定server_id。

#設定server_id
server_id = 1
#開啟binlog日誌
log-bin = mysql-bin

2、在主庫上建立複製使用者

create user '使用者名稱'@'%' identified by '密碼';
grant replication slave on *.* to '使用者名稱'@'%';

3、在從庫上設定server_id

#設定server_id
server_id = 10

4、備份主庫上的資料

mysqldump -u root -p --all-databases --routines --events --triggers --single-transaction --master-data > 匯出路徑

5、在從庫上恢復主庫匯出的資料

mysql -u root -p -f < 主庫備份檔案.sql

6、在從庫上執行 CHANGE MASTER TO 命令

CHANGE MASTER TO 
MASTER_HOST='主庫IP',
MASTER_USER='主庫複製使用者',
MASTER_PASSWORD='密碼',
MASTER_LOG_FILE='二進位制日誌名稱',
MASTER_LOG_POS=二進位制日誌位置;

二進位制日誌名稱和二進位制日誌位置,已經在備份主庫檔案中包含了,類似如下所示:

CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000016', MASTER_LOG_POS=47845;

7、從庫上執行 start slave,然後 show slave status\G; 檢視複製狀態;

 

三、設定主主複製

假設主庫分別是master1和master2。

1、設定master2為只讀

set @@global.read_only = on;

2、在master2上建立複製使用者,如果存在,則不用建立了

create user '使用者名稱'@'%' identified by '密碼';
grant replication slave on *.* to '使用者名稱'@'%';

3、確保master2已開啟二進位制日誌,檢查master2上的二進位制日誌的座標

show master status;

4、根據第2步的資訊,在master1上執行 CHANGE MASTER TO 命令

CHANGE MASTER TO 
MASTER_HOST='MASTER2主機IP',
MASTER_USER='MASTER2複製使用者',
MASTER_PASSWORD='密碼',
MASTER_LOG_FILE='二進位制日誌名稱',
MASTER_LOG_POS=二進位制日誌位置;

5、在master1上開啟 slave 模式

start slave;

6、設定master2為可讀寫

set @@global.read_only = off;

  

 四、設定多源複製

設定 server3 為 server1 和 server2 的從庫。

1、設定 server1 和 server2 的二進位制日誌和server_id,具體操作可參考上面。

2、在 server1 和 server2 上建立複製使用者,具體操作可參考上面。

3、在 server3 上設定 server_id。

4、備份 server1 和 server2 的資料。

5、在 server3 上恢復 server1 和 server2 上備份的資料。

6、在 server3 上,將複製儲存庫從 FILE 改為 TABLE,

stop slave;
set global master_info_repository = 'TABLE';
set global relay_log_info_repository = 'TABLE';

 還需要在配置檔案中修改:

[mysqld]
master-info-repository = TABLE
relay-log-info-repository = TABLE

7、在 server3 上,執行 CHANGE MASTER TO 命令,並命名通道名

CHANGE MASTER TO 
MASTER_HOST='server1主機IP',
MASTER_USER='server1複製使用者',
MASTER_PASSWORD='密碼',
MASTER_LOG_FILE='server1二進位制日誌名稱',
MASTER_LOG_POS=server1二進位制日誌位置 FOR CHANNEL 'server1';

CHANGE MASTER TO 
MASTER_HOST='server2主機IP',
MASTER_USER='server2複製使用者',
MASTER_PASSWORD='密碼',
MASTER_LOG_FILE='server2二進位制日誌名稱',
MASTER_LOG_POS=server2二進位制日誌位置 FOR CHANNEL 'server2';

8 、在 server3 上,為每個通道執行 START SLAVE FOR CHANNEL 語句

start slave for channel 'server1';
start slave for channel 'server2';

9、檢視同步狀態,show slave status\G;

要獲取指定通道的從庫狀態,show slave status for channel '通道名稱'\G;

 

五、設定複製篩選器

可以選擇要複製哪些表或資料庫,在主庫上,可以使用--binlog-do-db 和 --binlog-ignore-db 選項來選擇要記錄變更的資料庫,以控制二進位制日誌。更好的方法是控制從庫。

1、複製指定資料庫

CHANGE REPLICATION FILTER REPLICATE_DO_DB = (db1, db2);

2、複製指定表

CHANGE REPLICATION FILTER REPLICATE_DO_TABLE = ('db1.table1');

3、如果想使用萬用字元來選擇表

CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('db1.tb_%');

4、忽略資料庫

CHANGE REPLICATION FILTER REPLICATE_IGNORE_DB = (db1, db2);

5、忽略指定表

CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE = ('db1.table1');

  

六、將從庫由主從複製切換到鏈式複製

比如現在伺服器A為主庫,伺服器B和伺服器C為從庫,複製於伺服器A。現在想把伺服器C作為伺服器B的從庫。

1、在伺服器C上停止從庫執行

stop slave;
show slave status\G;

記錄下Relay_Master_Log_File和Exec_Master_Log_Pos的值

2、在伺服器B上停止從庫執行

stop slave;
show slave status\G;

記錄下Relay_Master_Log_File和Exec_Master_Log_Pos的值

3、將伺服器B的日誌位置與伺服器C的進行比較,找出哪一個是伺服器A最新同步,通常,伺服器C先停止從庫執行,伺服器B的日誌會更靠前。

4、在伺服器C上,使用 START SLAVE UNTIL 語句將其同步到伺服器B的日誌位置:

START SLAVE UNTIL MASTER_LOG_FILE='上一步中伺服器B日誌名稱', MASTER_LOG_POS=上一步中伺服器B日誌位置;

5、在伺服器C上,檢查 show slave status 中 Exec_Master_Log_Pos 和 Until_Log_Pos 兩者應該相同。

6、在伺服器B上,檢視主庫狀態,啟動從庫。

show master status;
start slave;
show slave status\G;

7、在伺服器C上,停止從庫執行,執行 CHANGE MASTER TO 命令。

stop slave;
CHANGE MASTER TO
MASTER_HOST='伺服器B的IP',
MASTER_USER='伺服器B複製使用者',
MASTER_PASSWORD='密碼',
MASTER_LOG_FILE='上一步中通過show master status獲取日誌名稱',
MASTER_LOG_POS=上一步中通過show master status獲取日誌位置;

8、在伺服器C上,啟動複製並檢視狀態

start slave;
show slave status\G;

  

 七、將鏈式複製切換到主從複製

伺服器A->伺服器B->伺服器C,如果想讓伺服器C直接作為伺服器A的從庫,該怎麼做?

1、在伺服器B上,停止從庫執行,並記錄主庫狀態

stop slave;
show master status\G;

2、伺服器C上,確保從庫的延遲已被追上,Relay_Master_Log_File和Exec_Master_Log_Pos應該等於伺服器B上主庫狀態。

一旦延遲被追上,就停止從庫的執行。

stop slave;

3、在伺服器B上,從 show slave status 中獲取伺服器A的日誌座標值(Relay_Master_Log_File和Exec_Master_Log_Pos),並啟動從庫

show slave status\G;
start slave;

4、在伺服器C上,停止從庫執行,並執行 CHANGE MASTER TO 命令,指向伺服器A

stop slave;
CHANGE MASTER TO 
MASTER_HOST='伺服器A的IP',
MASTER_USER='伺服器A的複製使用者',
MASTER_PASSWORD='密碼',
MASTER_LOG_FILE='上一步中獲取的日誌',
MASTER_LOG_POS=上一步中獲取的日誌位置;

5、在伺服器C上,開啟從庫,並檢視狀態。

start slave;
show slave status\G;

  

八、設定延遲複製

為什麼需要延遲複製,有可能主庫上執行了一條災難性語句,你必須通過備份中的時間點恢復,如果資料庫大小過大,這將導致長時間停機。

為了避免出現這種情況,可以使用一個延遲的從庫,如果發生了災難,並且延遲的從庫還沒有執行這條災難性語句,則可以先停止複製,讓從庫跳過該災難語句,最後把從庫提升為主庫。

1、停止從庫執行

stop slave;

2、設定延遲時間,以秒為單位

CHANGE MASTER TO MASTER_DELAY = 3600;
start slave;

3、檢查從庫狀態

show slave status\G;

SQL_Delay: 從庫延遲於主庫的秒數。

SQL_Remaining_Delay:延遲還剩餘的秒數,當保持延遲時,這個值是NULL。

Slave_SQL_Running_State:SQL執行緒的狀態

 

九、設定 GTID 複製

全域性事務識別符號 GTID 是在程式中建立的唯一識別符號,並與主庫上提交的每個事務相關聯。該識別符號是唯一的,不僅在主庫上,在其他從庫上,它都唯一。

上面描述的所有複製,都需要指明二進位制檔案和複製起點的位置,如果將一個從庫的主庫切換到另一個,就必須重新獲取二進位制檔案位置,這會很麻煩。

為了避免,可以使用基於 GTID 的複製,mysql 使用 GTID 自動檢測二進位制日誌的位置。

1、在所有資料庫中 my.cnf 中啟動 GTID

[mysqld]
gtid_mode = ON
enforce-gtid-consistency = 1
skip_slave_start

2、將主庫設定為只讀,確保主庫與從庫資料一致。

set @@global.read_only = on;

3、重新啟動所有從庫,使 GTID 生效。

4、重新啟動主庫。

5、在從庫上執行 CHANGE MASTER TO 命令來設定 GTID 複製

CHANGE MASTER TO
MASTER_HOST='主庫IP',
MASTER_PORT=3306,
MASTER_USER='複製使用者',
MASTER_PASSWORD='密碼',
MASTER_AUTO_POSITION=1;

6、在所有從庫上執行 start slave; 並檢視狀態。

 

十、設定半同步複製

預設情況下,複製是非同步的,主庫不知道寫入操作是否到達從庫,如果主庫與從庫間存在延遲,主庫崩了,尚未到達從庫的那些資料就會丟失。

為了解決這種問題,半同步複製,主庫會一直等待,直到至少有一個從庫接收到寫入的資料。

1、在主庫上,安裝 rpl_semi_sync_master 外掛

install plugin rpl_semi_sync_master SONAME 'semisync_master.so';

windows下請使用如下:

install plugin rpl_semi_sync_master SONAME 'semisync_master.dll';

2、確認外掛已啟用

select plugin_name, plugin_status from information_schema.plugins where plugin_name like '%semi%';

3、開啟半同步複製並調整超時時間

set @@global.rpl_semi_sync_master_enabled=1;
set @@global.rpl_semi_sync_master_timeout=100;

4、在從庫上,安裝 rpl_semi_sync_slave 外掛

install plugin rpl_semi_sync_slave SONAME 'semisync_slave.so';

windows下請使用如下:

install plugin rpl_semi_sync_slave SONAME 'semisync_slave.dll';

5、確認外掛已啟用

select plugin_name, plugin_status from information_schema.plugins where plugin_name like '%semi%';

6、在從庫上,啟用半同步複製,並重新啟動從庫IO執行緒

set global rpl_semi_sync_slave_enabld = 1;
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;

7、通過如下方式檢視半同步狀態

show status like 'rpl_semi_sync_master_clients';

檢視以半同步連線到主庫的客戶端數量

show status like 'rpl_semi_sync_master_status';

主庫在非同步和半同步複製之間切換,on表示半同步,off表示非同步。

相關文章