MySQL半同步復(fù)制與GTID實(shí)戰(zhàn)指南
三、半同步復(fù)制與 GTID 實(shí)踐筆記

3.1 半同步復(fù)制原理
- Master 執(zhí)行事務(wù)后,暫不提交,等待至少一個(gè) Slave 返回 ACK。
- Slave 的 IO 線程接收 Binlog 并寫入 Relay Log 后,向 Master 返回 ACK。
- Master 收到 ACK 后提交事務(wù),并向客戶端返回成功。
- 若在超時(shí)時(shí)間內(nèi)未收到 ACK(默認(rèn) 10 秒),自動(dòng)降級(jí)為異步復(fù)制。
- MySQL 5.6 使用
after_commit模式(先提交再等 ACK),存在數(shù)據(jù)風(fēng)險(xiǎn)。MySQL 5.7+ 默認(rèn)使用更安全的AFTER_SYNC模式。
3.2 gtid 模式
當(dāng)為啟用 gtid 時(shí)我們要考慮的問題
在 master 端的寫入時(shí)多用戶讀寫,在 slave 端的復(fù)制時(shí)單線程日志回放,所以 slave 端一定會(huì)延遲與 master 端
這種延遲在 slave 端的延遲可能會(huì)不一致,當(dāng) master 掛掉后 slave 接管,一般會(huì)挑選一個(gè)和 master 延遲日志最接近的充當(dāng)新的 master
那么為接管 master 的主機(jī)繼續(xù)充當(dāng) slave 角色并會(huì)指向到新的 master 上,作為其 slave
這時(shí)候按照之前的配置我們需要知道新的 master 上的 pos 的 id,但是我們無法確定新的 master 和 slave 之間差多
當(dāng)激活 GITD 之后
當(dāng) master 出現(xiàn)問題后,slave2 和 master 的數(shù)據(jù)最接近,會(huì)被作為新的 master
slave1 指向新的 master,但是他不會(huì)去檢測(cè)新的 master 的 pos id,只需要繼續(xù)讀取自己 gtid_next 即可
GTID 的簡(jiǎn)單工作流程
- 主庫執(zhí)行一個(gè)事務(wù),提交后自動(dòng)生成一個(gè)唯一的 GTID,記錄到 binlog 里;
- 從庫讀取主庫的 binlog,先記錄這個(gè) GTID(標(biāo)記為 “已收到”);
- 從庫執(zhí)行這個(gè)事務(wù),執(zhí)行完后把 GTID 標(biāo)記為 “已執(zhí)行”;
- 主從同步時(shí),從庫只會(huì)向主庫請(qǐng)求自己 “未執(zhí)行” 的 GTID 對(duì)應(yīng)的事務(wù)。
設(shè)置 gtid
#在master端和slave端開啟gtid模式
[root@mysql-node1 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock server-id=1 log-bin=mysql-bin gtid_mode=ON enforce-gtid-consistency=ON symbolic-links=0 [root@mysql-node1 ~]# /etc/init.d/mysqld restart

[root@mysql-node2 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock server-id=2 log-bin=mysql-bin gtid_mode=ON enforce-gtid-consistency=ON symbolic-links=0 [root@mysql-node2 ~]# /etc/init.d/mysqld restart

[root@mysql-node3 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock server-id=3 log-bin=mysql-bin gtid_mode=ON enforce-gtid-consistency=ON symbolic-links=0 三臺(tái)主機(jī)全部執(zhí)行 /etc/init.d/mysqld restart

#查看gtid狀態(tài)
mysql> show variables like '%gtid%'; +----------------------------------+-----------+ | Variable_name | Value | +----------------------------------+-----------+ | binlog_gtid_simple_recovery | ON | | enforce_gtid_consistency | ON | | gtid_executed | | | gtid_executed_compression_period | 0 | | gtid_mode | ON | | gtid_next | AUTOMATIC | | gtid_owned | | | gtid_purged | | | session_track_gtids | OFF | +----------------------------------+-----------+ 9 rows in set (0.01 sec)
gtid開啟前

gtid開啟后

#停止slave端 [root@mysql2 ~]# mysql -uroot -proot mysql> stop slave; Query OK, 0 rows affected (0.00 sec) [root@mysql3 ~]# mysql -uroot -proot mysql> stop slave; Query OK, 0 rows affected (0.01 sec)

#開啟slave端的gtid
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='swp', MASTER_PASSWORD='swp', MASTER_AUTO_POSITIO N=1;
Query OK, 0 rows affected, 7 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 172.25.254.10
Master_User: swp
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 158
Relay_Log_File: mysql3-relay-bin.000002
Relay_Log_Pos: 375
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 158
Relay_Log_Space: 587
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 10
Master_UUID: 3f9a4795-332a-11f1-beae-000c29059db4
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 10
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.00 sec)
3.3.啟用半同步模式
在 master 端配置啟用半同步模式
[root@mysql-node1 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock server-id=1 log-bin=mysql-bin gtid_mode=ON enforce-gtid-consistency=ON rpl_semi_sync_master_enabled=1 #開啟半同步功能 symbolic-links=0

[root@mysql-node1 ~]# mysql -uroot -proot
#安裝半同步插件
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
#查看插件情況
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
1 row in set (0.01 sec)
#打開半同步功能 mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1; #查看半同步功能狀態(tài) mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +-------------------------------------------+------------+ | Variable_name | Value | +-------------------------------------------+------------+ | rpl_semi_sync_master_enabled | ON | | rpl_semi_sync_master_timeout | 10000 | | rpl_semi_sync_master_trace_level | 32 | | rpl_semi_sync_master_wait_for_slave_count | 1 | | rpl_semi_sync_master_wait_no_slave | ON | | rpl_semi_sync_master_wait_point | AFTER_SYNC | +-------------------------------------------+------------+ mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 0 | | Rpl_semi_sync_master_net_avg_wait_time | 0 | | Rpl_semi_sync_master_net_wait_time | 0 | | Rpl_semi_sync_master_net_waits | 0 | | Rpl_semi_sync_master_no_times | 0 | | Rpl_semi_sync_master_no_tx | 0 | | Rpl_semi_sync_master_status | ON | | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 0 | | Rpl_semi_sync_master_tx_wait_time | 0 | | Rpl_semi_sync_master_tx_waits | 0 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | | Rpl_semi_sync_master_yes_tx | 0 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec)

在 slave 端開啟半同步功能

[root@mysql-slave和slave2都做 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock server-id=1 log-bin=mysql-bin gtid_mode=ON enforce-gtid-consistency=ON rpl_semi_sync_slave_enabled=1 #開啟半同步功能 symbolic-links=0


[root@mysql-slave和slave2都做# mysql -uroot -proot mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; Query OK, 0 rows affected (0.01 sec) mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1; Query OK, 0 rows affected (0.00 sec) mysql> STOP SLAVE IO_THREAD; #重啟io線程,半同步才能生效 Query OK, 0 rows affected (0.00 sec) mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 2 rows in set (0.01 sec) mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
3.4.測(cè)試
在 master 端寫入數(shù)據(jù)
mysql> insert into baibai.userlist values ('xixi','12340');
Query OK, 1 row affected (0.00 sec)
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 4 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx #未同步數(shù)據(jù)0筆 | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 633 |
| Rpl_semi_sync_master_tx_wait_time | 633 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx #已同步數(shù)據(jù)1筆| 1 |
+--------------------------------------------+-------+
模擬故障:
#在slave端 [root@mysql-slave2]# mysql -uroot -proot mysql> STOP SLAVE IO_THREAD; Query OK, 0 rows affected (0.00 sec) [root@mysql-slave]# mysql -uroot -proot mysql> STOP SLAVE IO_THREAD; Query OK, 0 rows affected (0.00 sec)

#在master端插入數(shù)據(jù)
mysql> insert into lee.userlist values ('baibai','12340');
Query OK, 1 row affected (10.00 sec) #10秒超時(shí)
mysql> SHOW STATUS LIKE 'Rpl_semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 2 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 | #一筆數(shù)據(jù)為同步
| Rpl_semi_sync_master_status | OFF | #自動(dòng)轉(zhuǎn)為異步模式,當(dāng)slave恢復(fù)
| Rpl_semi_sync_master_timefunc_failures | 0 | #會(huì)自動(dòng)恢復(fù)
| Rpl_semi_sync_master_tx_avg_wait_time | 981 |
| Rpl_semi_sync_master_tx_wait_time | 981 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
3.5 核心參數(shù)說明
| 參數(shù) | 說明 |
|---|---|
rpl_semi_sync_master_enabled | Master 是否啟用半同步 |
rpl_semi_sync_slave_enabled | Slave 是否啟用半同步 |
rpl_semi_sync_master_timeout | 等待 ACK 超時(shí)時(shí)間(毫秒),默認(rèn) 10000 |
rpl_semi_sync_master_wait_for_slave_count | 至少需要等待幾個(gè) Slave 返回 ACK |
rpl_semi_sync_master_wait_point | AFTER_SYNC(推薦) / AFTER_COMMIT |
gtid_mode | 是否開啟 GTID |
enforce_gtid_consistency | 強(qiáng)制 GTID 一致性,開啟 GTID 時(shí)必須啟用 |
3.6 最佳實(shí)踐建議
- 生產(chǎn)環(huán)境推薦 GTID + 半同步組合使用,兼顧高可用與數(shù)據(jù)一致性。
- 設(shè)置合理的
rpl_semi_sync_master_timeout(如 5–10 秒),避免網(wǎng)絡(luò)抖動(dòng)影響寫入。 - 監(jiān)控
Rpl_semi_sync_master_clients和Rpl_semi_sync_master_status,及時(shí)發(fā)現(xiàn)半同步降級(jí)。 - 主從切換時(shí),GTID 模式可大幅簡(jiǎn)化操作,無需手動(dòng)找 position。
_COMMIT| |gtid_mode| 是否開啟 GTID | |enforce_gtid_consistency` | 強(qiáng)制 GTID 一致性,開啟 GTID 時(shí)必須啟用 |
3.6 最佳實(shí)踐建議
- 生產(chǎn)環(huán)境推薦 GTID + 半同步組合使用,兼顧高可用與數(shù)據(jù)一致性。
- 設(shè)置合理的
rpl_semi_sync_master_timeout(如 5–10 秒),避免網(wǎng)絡(luò)抖動(dòng)影響寫入。 - 監(jiān)控
Rpl_semi_sync_master_clients和Rpl_semi_sync_master_status,及時(shí)發(fā)現(xiàn)半同步降級(jí)。 - 主從切換時(shí),GTID 模式可大幅簡(jiǎn)化操作,無需手動(dòng)找 position。
- 半同步降級(jí)為異步后,待從庫恢復(fù)會(huì)自動(dòng)切回,無需人工干預(yù)。
到此這篇關(guān)于MySQL半同步復(fù)制與GTID實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)MySQL半同步復(fù)制與GTID內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySql數(shù)據(jù)庫之a(chǎn)lter表的SQL語句集合
mysql之a(chǎn)lter表的SQL語句集合,包括增加、修改、刪除字段,重命名表,添加、刪除主鍵等。本文給大家介紹MySql數(shù)據(jù)庫之a(chǎn)lter表的SQL語句集合,感興趣的朋友一起學(xué)習(xí)吧2016-04-04
mysql數(shù)據(jù)庫navicat數(shù)據(jù)同步時(shí)誤刪除部分?jǐn)?shù)據(jù)的解決
本文主要介紹了mysql數(shù)據(jù)庫navicat數(shù)據(jù)同步時(shí)誤刪除部分?jǐn)?shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-04-04
關(guān)于MySql數(shù)據(jù)庫Update批量更新不同值的實(shí)現(xiàn)方法
這篇文章主要介紹了關(guān)于MySql數(shù)據(jù)庫Update批量更新不同值的實(shí)現(xiàn)方法,數(shù)據(jù)庫管理系統(tǒng)可以通過SQL管理數(shù)據(jù)庫,定義和操作數(shù)據(jù),維護(hù)數(shù)據(jù)的完整性和安全性,需要的朋友可以參考下2023-05-05
解決MySQL5.1安裝時(shí)出現(xiàn)Cannot create windows service for mysql.error
這篇文章主要介紹了解決MySQL5.1安裝時(shí)出現(xiàn)Cannot create windows service for mysql.error:0問題的方法2016-06-06
MySQL中報(bào)錯(cuò):Can’t find file: ‘./mysql/plugin.frm’的解決方法
這篇文章主要給大家介紹了關(guān)于在MySQL中報(bào)錯(cuò):Can't find file: './mysql/plugin.frm'的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
解決SQL文件導(dǎo)入MySQL數(shù)據(jù)庫1118錯(cuò)誤的問題
在使用Navicat導(dǎo)入SQL文件時(shí),有時(shí)會(huì)遇到報(bào)錯(cuò)問題,這通常與MySQL版本差異或嚴(yán)格模式設(shè)置有關(guān),若報(bào)錯(cuò)提示rowsize長(zhǎng)度過長(zhǎng),可能是因?yàn)镸ySQL的嚴(yán)格模式開啟導(dǎo)致,解決方法是檢查嚴(yán)格模式是否開啟,若開啟則需關(guān)閉2024-10-10

