MySQL中半同步模式的實現(xiàn)示例
1 半同步簡介: 解決主從數(shù)據(jù)一致性問題
MySQL 半同步復制是一種機制,旨在解決主從數(shù)據(jù)的一致性問題。它的主要目標是在主服務器提交事務之前等待至少一個從服務器確認收到了該事務的二進制日志事件。這樣可以確保主服務器上的事務在從服務器上至少有一個副本,從而提高數(shù)據(jù)可靠性。
在默認情況下,MySQL的復制是異步的,這意味著主服務器及其從服務器是獨立的。異步復制可以提供最佳的性能,因為主服務器在將更新的數(shù)據(jù)寫入它的二進制日志(Binlog)文件中后,無需等待驗證更新數(shù)據(jù)是否已經(jīng)復制到從服務器中,就可以自由處理其它進入的事務處理請求。但這也同時帶來了很高的風險,如果在主服務器或從服務器端發(fā)生故障,會造成主從數(shù)據(jù)的不一致,甚至在恢復時造成數(shù)據(jù)丟失。
從MySQL5.5開始引入了一種半同步復制功能,該功能可以確保主服務器和訪問鏈中至少一臺從服務器之間的數(shù)據(jù)一致性和冗余。在這種配置結構中,一臺主服務器和其許多從服務器都進行了配置,這樣在復制拓撲中,至少有一臺從服務器在父主服務器進行事務處理前,必須確認更新已經(jīng)收到并寫入了其中繼日志 (Relay Log)。當出現(xiàn)超時,源主服務器必須暫時切換到異步復制模式重新復制,直到至少有一臺設置為半同步復制模式的從服務器及時收到信息。 繼5.5半同步復制后,MySQL5.6又對其進行了優(yōu)化和改進,其中有兩個地方較為重要:
1> 在主從切換后,在傳統(tǒng)的方式里,需要找到binlog和POS點,然后更改master指向,而在mysql5.6里,你無須再知道binlog和POS點,你只需要知道m(xù)aster的IP、端口,賬號密碼即可,因為同步復制是自動的,mysql通過內(nèi)部機制GTID自動找點同步。 ?
2> 多線程復制,以前的版本,同步復制是單線程的,只能一個一個執(zhí)行,在MySQL5.6里,可以做到多個庫之間的多線程復制,但一個庫里的表,多線程復制是無效的。
1.用戶線程寫入完成后master中的dump會把日志推送到slave端
2.slave中的io線程接收后保存到relaylog中繼日志
3.保存完成后slave向master端返回ack
4.在未接受到slave的ack時master端時不做提交的,一直處于等待當收到ack后提交到存儲引擎
5.在5.6版本中用到的時after_commit模式,after_commit模式時先提交在等待ack返回后輸出ok
2 實現(xiàn)半同步模式實踐操作
2.1 MASTER
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 | +----------------------+---------------+
[root@mysql-01 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock symbolic-links=0 log_bin=mysql-bin server_id=10 gtid_mode=ON enforce-gtid-consistency=ON rpl_semi_sync_master_enabled=1 # 增加模塊 master 端自啟動 [root@mysql-01 ~]# systemctl restart mysqld # 查看模塊是否安裝成功 mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS -> FROM INFORMATION_SCHEMA.PLUGINS -> WHERE PLUGIN_NAME LIKE '%semi%'; +----------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +----------------------+---------------+ | rpl_semi_sync_master | ACTIVE | +----------------------+---------------+ 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 | -- (1) 表示當前有多少個從服務器客戶端正在進行半同步復制。 | Rpl_semi_sync_master_net_avg_wait_time | 0 | -- (2) 表示主服務器在等待從服務器確認時網(wǎng)絡平均等待時間(毫秒)。這里的值為0,表示沒有平均網(wǎng)絡等待時間。 | Rpl_semi_sync_master_net_wait_time | 0 | -- (3) 表示主服務器在網(wǎng)絡等待上的總時間(毫秒)。這里的值同樣為0,表示沒有總的網(wǎng)絡等待時間。 | Rpl_semi_sync_master_net_waits | 0 | -- (4) 表示主服務器因網(wǎng)絡原因等待的次數(shù)。這里的值為0,表示沒有因網(wǎng)絡原因導致的等待。 | Rpl_semi_sync_master_no_times | 0 | -- (5) 表示主服務器沒有等待任何從服務器確認的次數(shù)。這里的值為0,表示所有事務都至少等待了一個從服務器的確認。 | Rpl_semi_sync_master_no_tx | 0 | -- (6) 表示主服務器沒有提交任何事務的次數(shù)。這里的值為0,表示所有事務都進行了半同步復制。 | Rpl_semi_sync_master_status | ON | -- (7) 表示半同步復制當前是否啟用。在這里,半同步復制是啟用的。 | Rpl_semi_sync_master_timefunc_failures | 0 | -- (8) 表示由于時間函數(shù)失敗而導致半同步復制失敗的次數(shù)。這里的值為0,表示沒有時間函數(shù)失敗。 | Rpl_semi_sync_master_tx_avg_wait_time | 0 | -- (9) 表示主服務器在等待從服務器確認事務時的平均等待時間(毫秒)。這里的值為0,表示沒有平均等待時間。 | Rpl_semi_sync_master_tx_wait_time | 0 | -- (10) 表示主服務器等待從服務器確認事務的總等待時間(毫秒)。這里的值為0,表示沒有總的等待時間。 | Rpl_semi_sync_master_tx_waits | 0 | -- (11) 表示主服務器等待從服務器確認事務的次數(shù)。這里的值為0,表示沒有等待時間。 | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | -- (12) 表示主服務器在等待從服務器確認時回溯binlog位置的次數(shù)。這里的值為0,表示沒有回溯binlog位置。 | Rpl_semi_sync_master_wait_sessions | 0 | -- (13) 表示主服務器等待從服務器確認事務時涉及的會話數(shù)量。這里的值為0,表示沒有等待會話。 | Rpl_semi_sync_master_yes_tx | 0 | -- (14) 表示主服務器成功提交事務并得到從服務器確認的次數(shù)。這里的值為0,表示沒有事務成功提交并得到確認。 +--------------------------------------------+-------+
2.2 SLAVE 1
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; [root@mysql-02 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock symbolic-links=0 server_id=20 gtid_mode=ON enforce-gtid-consistency=ON rpl_semi_sync_slave_enabled=1 [root@mysql-02 ~]# systemctl restart mysqld [root@mysql-02 ~]# mysql -uroot -pOpenlab123! mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; # 查看模塊是否加載 +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+
2.3 SLAVE 2
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; [root@mysql-02 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock symbolic-links=0 server_id=30 gtid_mode=ON enforce-gtid-consistency=ON rpl_semi_sync_slave_enabled=1 [root@mysql-02 ~]# systemctl restart mysqld [root@mysql-02 ~]# mysql -uroot -pOpenlab123! mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; # 查看模塊是否加載 +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+
2.4 查看client鏈接狀態(tài)
再次回到MASTER
[root@mysql-01 ~]# systemctl restart mysqld mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 2 | # 發(fā)現(xiàn)鏈接客戶端變成了兩個 | 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 | +--------------------------------------------+-------+
2.5 SLAVE 服務器故障模擬
2.5.1 停止 SLAVE 的 IO_THREAD
# SLAVE 1 mysql> STOP SLAVE IO_THREAD; mysql> SHOW SLAVE STATUS\G # SLAVE 2 mysql> STOP SLAVE IO_THREAD; mysql> SHOW SLAVE STATUS\G
2.5.2 查看SLAVE 的IO線程是否關閉
2.5.3 查看 MASTER 上 client 的連接狀態(tài)
mysql> SHOW STATUS LIKE 'Rpl_semi%';
2.5.4 在MASTER端插入數(shù)據(jù)
mysql> insert into wawa values(7,'www.shuyan'); Query OK, 1 row affected (10.00 sec) # 會卡住十秒鐘然后從同步轉為異步,再插入數(shù)據(jù) mysql> SELECT * FROM wawa; +----+-----------------+ | id | name | +----+-----------------+ | 1 | wawa | | 2 | shuyan | | 3 | shuyan and wawa | | 4 | shuyan-------- | | 5 | shuyan.com | | 6 | 12333 | | 7 | www.shuyan | +----+-----------------+
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 | 0 | | Rpl_semi_sync_master_no_times | 1 | | Rpl_semi_sync_master_no_tx | 1 | # 一筆數(shù)據(jù)為同步 | Rpl_semi_sync_master_status | OFF | # 自動轉為異步模式,等待slave恢復 | 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)
2.5.5 MASTER 還能寫入數(shù)據(jù)的原因
為什么還能寫入呢?是因為他在超過超時時間的時候,模式由同步模式轉為異步模式
開啟從服務器的 IO_THREAD 線程
# SLAVE 1 mysql> start slave io_thread; # SLAVE 2 mysql> start slave io_thread; # 在SLAVE上發(fā)現(xiàn)數(shù)據(jù)已經(jīng)同步過來了 mysql> select * from shuyan.wawa; +----+-----------------+ | id | name | +----+-----------------+ | 1 | wawa | | 2 | shuyan | | 3 | shuyan and wawa | | 4 | shuyan-------- | | 5 | shuyan.com | | 6 | 12333 | | 7 | www.shuyan | +----+-----------------+
在從服務器開啟半同步復制時,主服務器會在等待從服務器響應之前設置一個超時時間。如果超過這個時間還沒有收到從服務器的響應,主服務器會自動轉換為異步模式。當從服務器恢復連接時,它會自動接收到主服務器在此期間插入的所有數(shù)據(jù)。
當從服務器IO_THREAD 線程 恢復連接時,從服務器會按照 GTID 的順序接收并應用來自主服務器的事務。
當從服務器的 I/O 線程恢復連接時,它會查找 gtid_executed 列表中缺失的 GTID,并從相應的二進制日志文件和位置開始復制。這樣,從服務器會按照 GTID 的順序接收并應用來自主服務器的事務,從而保證數(shù)據(jù)的一致性和完整性
MySQL 半同步復制可以通過 GTID(全局事務標識符)來比對數(shù)據(jù)。當從服務器恢復連接時,它會根據(jù) GTID 查找主服務器上尚未應用的事務,并自動接收到這些事務。
到此這篇關于MySQL中半同步模式的實現(xiàn)示例的文章就介紹到這了,更多相關MySQL 半同步模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
MySQL性能優(yōu)化之路---修改配置文件my.cnf
mysql數(shù)據(jù)庫的優(yōu)化,算是一個老生常談的問題了,網(wǎng)上也有很多關于各方面性能優(yōu)化的例子,今天我們要談的是MySQL 系統(tǒng)參數(shù)的優(yōu)化即優(yōu)化my.cnf文件2014-06-06MySQL數(shù)據(jù)庫入門之備份數(shù)據(jù)庫操作詳解
這篇文章主要介紹了MySQL數(shù)據(jù)庫入門之備份數(shù)據(jù)庫操作,結合實例形式詳細分析了MySQL備份數(shù)據(jù)庫基本操作命令與相關注意事項,需要的朋友可以參考下2020-05-05如何解決Mysql報錯Deadlock found when trying to
這篇文章主要介紹了如何解決Mysql報錯Deadlock found when trying to get lock;try restarting transaction問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-055招帶你輕松優(yōu)化MySQL count(*)查詢性能
最近在公司優(yōu)化了幾個慢查詢接口的性能,總結了一些心得體會拿出來跟大家一起分享一下,文中的示例代碼講解詳細,希望對大家會有所幫助2022-11-11MYSQL安裝時解決要輸入current root password的解決方法
在裝MYSQL的時候發(fā)現(xiàn)要輸入current root password不記得以前在電腦里裝過(你的系統(tǒng)曾經(jīng)裝過MYSQL在重裝就會要求輸入原來設定的密碼,如果是第一次安裝就不會出現(xiàn)),在網(wǎng)上苦苦搜尋解決方法。2011-07-07