MySQL支持一臺主庫同時向多臺從庫進行復制,從庫同時也可以作為其他從服務器的主庫,實現鏈狀復制。
1、MySQL支持的binlog二進制日志復制類型
- 基于語句(statement)的復制
? 在主服務器上執行SQL語句,在從服務器上執行同樣的語句。MySQL默認采用基于語句的復制,效率比較高。
- 基于行(row)的復制
把改變的內容復制過去,而不是把命令在從服務器上執行一遍。從MySQL 5.0開始支持。
- 混合型(mixed)的復制
默認采用基于語句的復制,一旦發現基于語句的無法精確復制時,就會采用基于行的復制。
主從復制原理
主節點
1、當主節點上進行 insert、update、delete 操作時,會按照時間先后順序寫入到 binlog 中; 2、當從節點連接到主節點時,主節點會創建一個叫做 binlog dump 的線程;一個主節點有多少個從節點,就會創建多少個 binlog dump 線程;
3、當主節點的 binlog 發生變化的時候,也就是進行了更改操作,binlog dump 線程就會通知從節點 (Push模式),并將相應的binlog 內容發送給從節點。
從節點
當開啟主從同步的時候,從節點會創建兩個線程用來完成數據同步的工作。
I/O線程: 此線程連接到主節點,主節點上的 binlog dump 線程會將 binlog 的內容發送給此線程。此線程接收到 binlog 內容后,再將內容寫入到本地的 relay log。
SQL線程: 該線程讀取 I/O 線程寫入的 relay log,并且根據 relay log 的內容對從數據庫做對應的操作。
為什么要做主從復制
實時災備,用于故障切換 ? 負載平衡 ? 讀寫分離,提高并發能力
配置主從同步
準備兩臺機器--已經部署好MySQL
主機名 | IP | 版本 | |
master | 192.168.1.128 | 主機 | |
slave | 192.168.1.129 | 從機 |
首先配置好兩臺主機的/etc/my.cnf
注意:server_id不能一樣
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server_id=129
log-bin=binlog
啟動MySQL
/etc/init.d/mysqld start
- 查看server_id的命令
select @@server_id
給master配置同步賬號并授予權限
create user 'rep'@'%' identified by '123';
grant replication slave on *.* to 'rep'@'%';
- 查看權限
show grants for 'rep'@'%';
- 鎖表設置只讀
為后面備份準備,注意生產環境要提前申請停機時間;
注意:測試鎖表后不可以可以創建數據庫
如果超過設置時間不操作會自動解鎖。
flush tables with read lock;
unlock tables;----解鎖命令
- 查看主庫狀態
注意記住file文件的編號以及position的編號
配置從主機:
設定從庫向主庫同步
change replication source to source_host='192.168.1.128',source_user='rep',source_password='123',source_log_file='binlog.000003',source_log_pos=1024,source_ssl=1;
啟動從庫同步開關
start replica;
查看狀態
start replica;
測試:
在主庫中創建數據庫 從庫中查看
從庫
查看主庫有多少從庫
show replicas;
主從復制進階
延時同步
通過人為配置從庫和主庫延時N小時可以實現延時同步,延時同步可以解決數據庫故障出現的數據丟失問題(物理損壞如直接使用rm刪除數據庫數據和邏輯損壞如使用drop命令刪除數據庫)。
注意延時同步是通過配置從庫延時來達到延時同步
配置從庫延時同步,設置sql線程延遲300秒后讀取relay log
首先關閉從庫開關
stop replica;
配置從庫延時同步,設置sql線程延遲300秒后讀取relay log
change replication source to source_delay=300;
開啟從庫同步
start replica;
進行延時測試
在主庫中創建relay_test的庫,relay_test的庫中創建t1的庫表插入數據
現在在主庫中刪除relay數據庫,模式誤觸刪除。測試延時同步的作用
在sql線程延遲300秒時間內發現誤刪除數據庫則立馬停止從庫的sql線程
stop slave sql_thread;
找到誤刪前relay log的起點和終點
找到relay_log文件的位置
show replica status\G;
輸入以下命令,找到誤刪數據的位置
show relaylog events in "slave-relay-bin.000002";
將relay log進行備份
mysqlbinlog --start-position=584 --stop-position=1962 /data/mysql/slave-relay-bin.000002 > /tmp/relay.sql
恢復誤刪除的數據庫
source /tmp/relay.sql;
在從庫中查看被主庫刪除的relay_log
GTID同步
GTID是全局事務ID(global transaction identifier),其保證為每一個提交的事務可以生成一個唯一的ID。當事務提交時,MySQL Server在寫binlog的時候,會先寫一個類型為GTID_Event的特殊Binlog Event,指定下一個事務的GTID,然后再寫事務的Binlog。主從同步時GTID_Event和事務的Binlog 都會傳遞到從庫,從庫在執行的時候也是用同樣的GTID寫binlog,這樣主從同步以后,就可通過GTID確定從庫同步到的位置了。也就是說,無論是級聯情況,還是一主多從情況,都可以通過GTID自動找同步位置,而無需像之前那樣通過File_name和File_position找同步位置了。
首先配置數據庫的主庫和從庫/etc/my.cnf文件
vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server_id=128
log-bin=binlog
enforce_gtid_consistency=on
gtid_mode=ON
重新啟動數據庫
/etc/init.d/mysqld restart
在主庫的配置
建立同步賬號
create user 'rep'@'%' identified by '123';
grant replication slave on *.* to 'rep'@'%';
在從庫中的配置
設定從庫向主庫同步
change replication source to source_host='192.168.1.128',source_user='rep',source_password='123',source_auto_position=1, source_ssl=1;
開啟從庫的同步
start replica;
檢查從庫狀態
show replica status\G;
測試:
在主庫中創建test數據庫,在庫中創建t1的表
在從庫中查看
半同步復制
半同步復制的特性:
- 半同步復制必須是在主庫和從庫兩端都開啟時才行,從庫會在連接到主庫時告訴主庫它是不是配置了半同步。
- 如果半同步復制在主庫端是開啟了的,并且至少有一個半同步復制的從庫節點,那么此時主庫的事務線程在提交時會被阻塞并等待,等待的結果有兩種,第一種是至少一個從庫節點通知主庫自己已經收到了所有這個事務的binlog事件;第二種就是主庫一直等待直到超過配置的某一個時間點為止,此種情況下半同步復制將自動關閉,轉換為異步復制。
- 從庫節點只有在接收到某一個事務的所有binlog并將其寫入relay log文件之后才會通知主庫
在mysql5.5-5.6使用after_commit的模式下,客戶端事務在存儲引擎層提交后,在得到從庫確認的過程中,主庫宕機了,此時主庫在等待slave ACK的時候,雖然沒有返回到當前客戶端但是事務已經提交,其他客戶端會讀取到已經提交的事務,如果slave端還沒有讀到該事務的events,同時主庫發生了crash,然后切換到備庫,那么之前讀到的事務就不見了。如果主庫永遠啟動不了,那么實際上在主庫已經成功提交的事務在從庫上是找不到的,也就是數據丟失了。
為了解決上述問題,在mysql5.7版本增加了after_sync(無損復制)參數,并將其設置為默認的半同步方式。在mysql5.7.2引入的Loss-less Semi-Synchronous(無損復制)通過添加參數after_sync,使得主庫在commit事務之前等待slave的ACK,只有slave回復了ACK,主庫才會提交事務,這樣就保證了master和slave數據的一致性。
在mysql5.7.17又引入了**全同步**技術,全同步復制就是當主庫提交事務之后,所有的從庫節點必須收到并且apply這些事務,然后主庫線程才能繼續后續操作。
配置半同步復制
主的配置,加載插件
install plugin rpl_semi_sync_master soname 'semisync_master.so';
查看插件
show plugins;
開啟此開關,可寫入配置文件
set global rpl_semi_sync_master_enabled=1;
設置主等待從回復ACK的超時時間為3秒,默認是10秒,可寫入配置文件
set global rpl_semi_sync_master_timeout=3000;
從的配置
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
開啟此開關,可寫入配置文件
set global rpl_semi_sync_slave_enabled=1;
查看狀態
show status like 'rpl_semi_sync_slave_status';
發現還是關閉狀態此時---關閉io進程---開啟io進程刷新一下再次查看
測試:
在主庫中創建表
查看master成功接收到slave的回復的次數
show status like 'Rpl_semi_sync_master_yes_tx';
模擬從故障
停止從庫的io進程
stop slave io_thread;
關閉半同步開關
set global rpl_semi_sync_slave_enabled=0;
在主庫中插入t2表的數據看一下主庫反應---可以看到會等待一個超時時間
發現主關閉了半同步復制
show status like 'Rpl_semi_sync_master_status';