搭建MySQL主從複製及原理詳解
搭建MySQL主從複製及原理詳解
MySQL的複製有3中常見架構,分別是一主多從複製架構、多級複製架構和雙主複製架構。本片文章主要講解的是一主多從架構及其搭建過程,其它兩種有興趣的讀者可以留言。
1.複製簡述
MySQL從3.23版本開始提供複製的功能。複製是指將主資料庫的DDL和DML操作通過二進位制日誌傳到複製伺服器(也叫從庫)上,然後在從庫上對這些日誌重新執行(也叫重做),從而使得從庫和主庫的資料保持同步。
MySQL支援一臺主庫同時向多臺從庫進行復制,從庫同時也可以作為其他伺服器的主庫,實現鏈狀的複製。
MySQL複製的優點主要包括以下3個方面:
- 如果主庫出現問題,可以快速切換到從庫提供服務;
- 可以在從庫上執行查詢操作,降低主庫的訪問壓力;
- 可以在從庫上執行備份,以避免備份期間影響主庫的服務。
2.複製原理
(1)首先,MySQL主庫在事務提交時會把資料變更作為事件Events記錄在二進位制日誌檔案Binlog中;MySQL主庫上的sync_binlog引數控制Binlog日誌重新整理到磁碟。
(2)主庫推送二進位制日誌檔案Binlog中的事件到從庫的中繼日誌Relay Log,之後從庫根據中繼日誌Relay Log重做資料變更操作,通過邏輯複製以此來達到主庫和從庫的資料一致。
MySQL通過 3個執行緒來完成主從庫間的資料複製:其中Binlog Dump執行緒跑在主庫上, I/O執行緒和SQL執行緒跑在從庫上。當在從庫上啟動複製(START SLAVE)時,首先建立 I/O執行緒連線主庫,主庫隨後建立Binlog Dump執行緒讀取資料庫事件併發送給 I/O執行緒,I/O執行緒獲取到事件資料後更新到從庫的中繼日誌Relay Log中去,之後從庫上的SQL執行緒讀取中繼日誌Relay Log中更新的資料庫事件並應用,如下圖所示:
<img src="C:\Users\50312\AppData\Roaming\Typora\typora-user-images\image-20201207083143526.png" alt="image-202
01207083143526" style="zoom:80%;" />
3.複製涉及的各類檔案
二進位制日誌(Binlog)
二進位制日誌檔案(Binlog)會把 MySQL 中的所有資料修改操作以二進位制的形式記錄到日誌檔案中,包括Create、Drop、Insert、Update、Delete操作等,但二進位制日誌檔案(Binlog)不會記錄Select操作,因為Select操作並不修改資料。
二進位制日誌檔案Binlog格式有以下3種:
- Statement:基於SQL語句級別的Binlog,每條修改資料的SQL都會儲存到Binlog裡
- Row:基於行級別,記錄每一行資料的變化,也就是將每行資料的變化都記錄到Binlog裡面,記錄得非常詳細,但是並不記錄原始SQL;在複製的時候,並不會因為儲存過程或觸發器造成主從庫資料不一致的問題,但是記錄的日誌量較Statement格式要大得多。
- Mixed:混合Statement和Row模式,預設情況下采用Statement模式記錄,某些情況下會切換到Row模式,例如SQL中包含與時間、使用者相關的函式等。
中繼日誌(Relay Log)
中繼日誌檔案Relay Log的檔案格式、內容和二進位制日誌檔案Binlog一樣,唯一的區別在於從庫上的SQL執行緒在執行完當前中繼日誌檔案Relay Log中的事件之後,SQL執行緒會自動刪除當前中繼日誌檔案Relay Log,避免從庫上的中繼日誌檔案Relay Log佔用過多的磁碟空間。
4.搭建步驟
關閉主從機器的防火牆
# systemctl stop iptables(需要安裝iptables服務)
# systemctl stop firewalld(預設)
# systemctl disable firewalld.service(設定開啟不啟動)
主伺服器配置
第一步:修改my.cnf檔案
修改主資料庫伺服器的配置檔案my.cnf,開啟BINLOG,並設定server-id的值。這兩個引數的修改需要重新啟動資料庫服務才可以生效。
[mysqld]
#啟用二進位制日誌
log-bin=mysql-bin
#伺服器唯一ID,一般取IP最後一段
server-id=136
第二步:重啟MySQL
# systemctl restart mysqld
第三步:授予Slave從機許可權
mysql> GRANT REPLICATION SLAVE ON *.* TO 'root'@'192.168.211.138'IDENTIFIED BY '123456';
第四步:重新整理許可權
FLUSH PRIVILEGES;
第五步:檢視master的狀態
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000006 | 120 | | | |
+------------------+----------+--------------+------------------+-------------------+
上圖表示,主機將從 mysql-bin.000006這個二進位制檔案的120行這個位置開始同步。
從伺服器配置
第一步:修改my.cnf檔案
[mysqld]
server-id=138
確保叢集中的各個伺服器的server-id唯一。
第二步:重啟並登入到從庫
先使用如下命令檢視從機是否在執行,是的話先停止執行
mysql> show slave status \G;
mysql> stop slave;
第三步:配置從資料庫伺服器
指定複製使用者,主資料庫伺服器IP、埠以及開始執行復制的日誌檔案和位置等,具體如下:
mysql> change master to
-> master_host='master_host_name',
-> master_port='master_host_port',
-> master_user='replication_user_name',
-> master_password='replication_password',
-> master_log_file='recorded_log_file_name',
-> master_log_pos=recorded_log_position;
舉例說明如下:
mysql> change master to
-> master_host='192.168.211.136',
-> master_port=3306,
-> master_user='root',
-> master_password='123456',
-> master_log_file='mysql-bin.000006',
-> master_log_pos=120;
第四步:啟動slave執行緒
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
第五步:檢查從伺服器複製功能狀態
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.211.136
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000006
Read_Master_Log_Pos: 120
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000006
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
。。。。。。。省略
Slave_IO_Running: Yes 說明從庫IO執行緒已就緒。
Slave_SQL_Running: Yes 說明從庫SQL執行緒已就緒。
測試
搭建成功之後,往主機中插入資料,看看從機中是否有資料
注: 如果出現複製不成功,可以使用
mysql> set global sql_slave_skip_counter =1; # 忽略一個錯誤
mysql> start slave
5.存在問題:主從延時
檢視主機處理狀態
可以通過SHOW PROCESSLIST命令在主庫上檢視Binlog Dump執行緒,從BinlogDump執行緒的狀態可以看到,MySQL 的複製是主庫主動推送日誌到從庫去的,是屬於“推”日誌的方式來做同步
mysql> mysql> show processlist \g;
+----+------+-----------------------+------+-------------+-------+-----------------------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------------------+------+-------------+-------+-----------------------------------------------------------------------+------------------+
| 3 | root | 192.168.211.1:50147 | NULL | Sleep | 11225 | | NULL |
| 6 | root | 192.168.211.138:52846 | NULL | Binlog Dump | 6174 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL |
| 7 | root | localhost | NULL | Query | 0 | init | show processlist |
+----+------+-----------------------+------+-------------+-------+-----------------------------------------------------------------------+------------------+
3 rows in set (0.00 sec)
檢視從機處理狀態
在從庫上通過SHOW PROCESSLIST可以看到 I/O執行緒和SQL執行緒,I/O執行緒等待主庫上的Binlog Dump執行緒傳送事件並更新到中繼日誌Relay Log,SQL執行緒讀取中繼日誌Relay Log並應用變更到資料庫:
mysql> show processlist \g;
+----+-------------+---------------------+------+---------+------+-----------------------------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+---------------------+------+---------+------+-----------------------------------------------------------------------------+------------------+
| 4 | root | 192.168.211.1:50207 | NULL | Sleep | 572 | | NULL |
| 6 | system user | | NULL | Connect | 6343 | Waiting for master to send event | NULL |
| 7 | system user | | NULL | Connect | 5859 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL |
| 9 | root | localhost | NULL | Query | 0 | init | show processlist |
+----+-------------+---------------------+------+---------+------+-----------------------------------------------------------------------------+------------------+
4 rows in set (0.00 sec)
解決方案
從MySQL複製流程可以瞭解到複製是非同步進行的。所以從庫上的資料和主庫會存在一定的延時,為了減少延時,可以考慮以下幾種解決方案:
- 因為SQLThread和IOThread是預設單執行緒,當主機的tps(每秒事務處理數)高於從機的Thread所能
承受範圍,則會出現從機複製延時
解決方案: 將thread改成多執行緒模式 MySQL5.6改表,MySQL5.7改GTID - 網路延時
解決方案: 主和從在一個網內 - IO延時
解決方案:slave server硬體升級
判斷延時:
show slave status中Seconds_Behind_Master=0則不延時