mysql半复制_mysql半同步复制
從MySQL5.5開始,MySQL以插件的形式支持半同步復(fù)制。如何理解半同步呢?首先我們來看看異步,全同步的概念
異步復(fù)制(Asynchronous replication)
MySQL默認(rèn)的復(fù)制即是異步的,主庫在執(zhí)行完客戶端提交的事務(wù)后會(huì)立即將結(jié)果返給給客戶端,并不關(guān)心從庫是否已經(jīng)接收并處理,這樣就會(huì)有一個(gè)問題,主如果crash掉了,此時(shí)主上已經(jīng)提交的事務(wù)可能并沒有傳到從上,如果此時(shí),強(qiáng)行將從提升為主,可能導(dǎo)致新主上的數(shù)據(jù)不完整。
全同步復(fù)制(Fully synchronous replication)
指當(dāng)主庫執(zhí)行完一個(gè)事務(wù),所有的從庫都執(zhí)行了該事務(wù)才返回給客戶端。因?yàn)樾枰却袕膸靾?zhí)行完該事務(wù)才能返回,所以全同步復(fù)制的性能必然會(huì)收到嚴(yán)重的影響。
半同步復(fù)制(Semisynchronous replication)
介于異步復(fù)制和全同步復(fù)制之間,主庫在執(zhí)行完客戶端提交的事務(wù)后不是立刻返回給客戶端,而是等待至少一個(gè)從庫接收到并寫到relay log中才返回給客戶端。相對(duì)于異步復(fù)制,半同步復(fù)制提高了數(shù)據(jù)的安全性,同時(shí)它也造成了一定程度的延遲,這個(gè)延遲最少是一個(gè)TCP/IP往返的時(shí)間。所以,半同步復(fù)制最好在低延時(shí)的網(wǎng)絡(luò)中使用。
下面來看看半同步復(fù)制的原理圖:
半同步復(fù)制的潛在問題
客戶端事務(wù)在存儲(chǔ)引擎層提交后,在得到從庫確認(rèn)的過程中,主庫宕機(jī)了,此時(shí),可能的情況有兩種
事務(wù)還沒發(fā)送到從庫上
此時(shí),客戶端會(huì)收到事務(wù)提交失敗的信息,客戶端會(huì)重新提交該事務(wù)到新的主上,當(dāng)宕機(jī)的主庫重新啟動(dòng)后,以從庫的身份重新加入到該主從結(jié)構(gòu)中,會(huì)發(fā)現(xiàn),該事務(wù)在從庫中被提交了兩次,一次是之前作為主的時(shí)候,一次是被新主同步過來的。
事務(wù)已經(jīng)發(fā)送到從庫上
此時(shí),從庫已經(jīng)收到并應(yīng)用了該事務(wù),但是客戶端仍然會(huì)收到事務(wù)提交失敗的信息,重新提交該事務(wù)到新的主上。
無數(shù)據(jù)丟失的半同步復(fù)制
針對(duì)上述潛在問題,MySQL 5.7引入了一種新的半同步方案:Loss-Less半同步復(fù)制。
針對(duì)上面這個(gè)圖,“Waiting Slave dump”被調(diào)整到“Storage Commit”之前。
當(dāng)然,之前的半同步方案同樣支持,MySQL 5.7.2引入了一個(gè)新的參數(shù)進(jìn)行控制-rpl_semi_sync_master_wait_point
rpl_semi_sync_master_wait_point有兩種取值
AFTER_SYNC
這個(gè)即新的半同步方案,Waiting Slave dump在Storage Commit之前。
AFTER_COMMIT
老的半同步方案,如圖所示。
半同步復(fù)制的安裝部署
要想使用半同步復(fù)制,必須滿足以下幾個(gè)條件:
1. MySQL 5.5及以上版本
2. 變量have_dynamic_loading為YES
3. 異步復(fù)制已經(jīng)存在
首先加載插件
因用戶需執(zhí)行INSTALL PLUGIN, SET GLOBAL, STOP SLAVE和START SLAVE操作,所以用戶需有SUPER權(quán)限。
主:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
從:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
查看插件是否加載成功
有兩種方式
1.
mysql> show plugins;
rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL
2.
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.00 sec)
啟動(dòng)半同步復(fù)制
在安裝完插件后,半同步復(fù)制默認(rèn)是關(guān)閉的,這時(shí)需設(shè)置參數(shù)來開啟半同步
主:
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
從:
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
以上的啟動(dòng)方式是在命令行操作,也可寫在配置文件中。
主:
plugin-load=rpl_semi_sync_master=semisync_master.so
rpl_semi_sync_master_enabled=1
從:
plugin-load=rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_slave_enabled=1
在有的高可用架構(gòu)下,master和slave需同時(shí)啟動(dòng),以便在切換后能繼續(xù)使用半同步復(fù)制
plugin-load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
rpl-semi-sync-master-enabled = 1
rpl-semi-sync-slave-enabled = 1
重啟從上的IO線程
mysql> STOP SLAVE IO_THREAD;
mysql> START SLAVE IO_THREAD;
如果沒有重啟,則默認(rèn)還是異步復(fù)制,重啟后,slave會(huì)在master上注冊(cè)為半同步復(fù)制的slave角色。
這時(shí)候,主的error.log中會(huì)打印如下信息:
2016-08-05T10:03:40.104327Z 5 [Note] While initializing dump thread for slave with UUID , found a zombie dump thread with the same UUID. Master is killing the zombie dump thread(4).
2016-08-05T10:03:40.111175Z 4 [Note] Stop asynchronous binlog_dump to slave (server_id: 2)
2016-08-05T10:03:40.119037Z 5 [Note] Start binlog_dump to master_thread_id(5) slave_server(2), pos(mysql-bin.000003, 621)
2016-08-05T10:03:40.119099Z 5 [Note] Start semi-sync binlog_dump to slave (server_id: 2), pos(mysql-bin.000003, 621)
查看半同步是否在運(yùn)行
主:
mysql> show status like 'Rpl_semi_sync_master_status';
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_status | ON |
+-----------------------------+-------+
1 row in set (0.00 sec)
從:
mysql> show status like 'Rpl_semi_sync_slave_status';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.20 sec)
這兩個(gè)變量常用來監(jiān)控主從是否運(yùn)行在半同步復(fù)制模式下。
至此,MySQL半同步復(fù)制搭建完畢~
事實(shí)上,半同步復(fù)制并不是嚴(yán)格意義上的半同步復(fù)制
當(dāng)半同步復(fù)制發(fā)生超時(shí)時(shí)(由rpl_semi_sync_master_timeout參數(shù)控制,單位是毫秒,默認(rèn)為10000,即10s),會(huì)暫時(shí)關(guān)閉半同步復(fù)制,轉(zhuǎn)而使用異步復(fù)制。當(dāng)master dump線程發(fā)送完一個(gè)事務(wù)的所有事件之后,如果在rpl_semi_sync_master_timeout內(nèi),收到了從庫的響應(yīng),則主從又重新恢復(fù)為半同步復(fù)制。
下面來測(cè)試一下
該驗(yàn)證分為三個(gè)階段
1. 在Slave執(zhí)行stop slave之前,主的insert操作很快就能返回。
2. 在Slave執(zhí)行stop slave后,主的insert操作需要10.01s才返回,而這與rpl_semi_sync_master_timeout參數(shù)的時(shí)間相吻合。
這時(shí),查看兩個(gè)狀態(tài)的值,均為“OFF”了。
同時(shí),主的error.log中打印如下信息:
2016-08-05T11:51:49.855452Z 6 [Warning] Timeout waiting for reply of binlog (file: mysql-bin.000003, pos: 1447), semi-sync up to file mysql-bin.000003, position 1196.
2016-08-05T11:51:49.855742Z 6 [Note] Semi-sync replication switched OFF.
3. 在Slave執(zhí)行start slave后,主的insert操作很快就能返回,此時(shí),兩個(gè)狀態(tài)的值也變?yōu)椤癘N”了。
同時(shí),主的error.log中會(huì)打印如下信息:
2016-08-05T11:52:40.477098Z 7 [Note] Start binlog_dump to master_thread_id(7) slave_server(2), pos(mysql-bin.000003, 1196)
2016-08-05T11:52:40.477168Z 7 [Note] Start semi-sync binlog_dump to slave (server_id: 2), pos(mysql-bin.000003, 1196)
2016-08-05T11:52:40.523475Z 0 [Note] Semi-sync replication switched ON at (mysql-bin.000003, 1447)
其它變量
環(huán)境變量
mysql> show variables like '%Rpl%';
+-------------------------------------------+------------+
| 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 |
| rpl_stop_slave_timeout | 31536000 |
+-------------------------------------------+------------+
7 rows in set (0.30 sec)
rpl_semi_sync_master_wait_for_slave_count
MySQL 5.7.3引入的,該變量設(shè)置主需要等待多少個(gè)slave應(yīng)答,才能返回給客戶端,默認(rèn)為1。
rpl_semi_sync_master_wait_no_slave
ON
默認(rèn)值,當(dāng)狀態(tài)變量Rpl_semi_sync_master_clients中的值小于rpl_semi_sync_master_wait_for_slave_count時(shí),Rpl_semi_sync_master_status依舊顯示為ON。
OFF
當(dāng)狀態(tài)變量Rpl_semi_sync_master_clients中的值于rpl_semi_sync_master_wait_for_slave_count時(shí),Rpl_semi_sync_master_status立即顯示為OFF,即異步復(fù)制。
說得直白一點(diǎn),如果我的架構(gòu)是1主2從,2個(gè)從都采用了半同步復(fù)制,且設(shè)置的是rpl_semi_sync_master_wait_for_slave_count=2,如果其中一個(gè)掛掉了,對(duì)于rpl_semi_sync_master_wait_no_slave設(shè)置為ON的情況,此時(shí)顯示的仍然是半同步復(fù)制,如果rpl_semi_sync_master_wait_no_slave設(shè)置為OFF,則會(huì)立刻變成異步復(fù)制。
狀態(tài)變量
mysql> show status like '%Rpl_semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 6 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 1120 |
| Rpl_semi_sync_master_tx_wait_time | 4483 |
| Rpl_semi_sync_master_tx_waits | 4 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 4 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
上述狀態(tài)變量中,比較重要的有以下幾個(gè)
Rpl_semi_sync_master_clients
當(dāng)前半同步復(fù)制從的個(gè)數(shù),如果是一主多從的架構(gòu),并不包含異步復(fù)制從的個(gè)數(shù)。
Rpl_semi_sync_master_no_tx
The number of commits that were not acknowledged successfully by a slave.
具體到上面的測(cè)試中,指的是insert into test.test values(2)這個(gè)事務(wù)。
Rpl_semi_sync_master_yes_tx
The number of commits that were acknowledged successfully by a slave.
具體到上面的測(cè)試中,指的是以下四個(gè)事務(wù)
create database test;
create table test.test(id int);
insert into test.test values(1);
insert into test.test values(3);
總結(jié)
1. 在一主多從的架構(gòu)中,如果要開啟半同步復(fù)制,并不要求所有的從都是半同步復(fù)制。
2. MySQL 5.7極大的提升了半同步復(fù)制的性能。
5.6版本的半同步復(fù)制,dump thread 承擔(dān)了兩份不同且又十分頻繁的任務(wù):傳送binlog 給slave ,還需要等待slave反饋信息,而且這兩個(gè)任務(wù)是串行的,dump thread 必須等待 slave 返回之后才會(huì)傳送下一個(gè) events 事務(wù)。dump thread 已然成為整個(gè)半同步提高性能的瓶頸。在高并發(fā)業(yè)務(wù)場(chǎng)景下,這樣的機(jī)制會(huì)影響數(shù)據(jù)庫整體的TPS 。
5.7版本的半同步復(fù)制中,獨(dú)立出一個(gè) ack collector thread ,專門用于接收slave 的反饋信息。這樣master 上有兩個(gè)線程獨(dú)立工作,可以同時(shí)發(fā)送binlog 到slave ,和接收slave的反饋。
總結(jié)
以上是生活随笔為你收集整理的mysql半复制_mysql半同步复制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 对象名无效_如何解决“SQL
- 下一篇: mysql数据库array_mysql数