本文分享自華爲雲社區《結合實戰,我爲MySQL主從複製總結了幾張圖!》,作者: 冰 河。
MySQL官方文檔
MySQL 主從複製官方文檔鏈接地址如下所示:
http://dev.mysql.com/doc/refman/8.0/en/replication.html
MySQL 主從複製方式
MySQL5.6 開始主從複製有兩種方式:基於日誌(binlog)、基於 GTID(全局事務標示符)。 這裏,我們主要講基於日誌(binlog)的複製。 關於GTID的主從複製,我們後面再詳細討論。
MySQL主從複製原理
MySQL主從複製原理,也稱爲A/B原理。
(1) Master 將數據改變記錄到二進制日誌(binary log)中,也就是配置文件 log-bin 指定的文件, 這些記錄叫做二進制日誌事件(binary log events);
(2) Slave 通過 I/O 線程讀取 Master 中的 binary log events 並寫入到它的中繼日誌(relay log);
(3) Slave 重做中繼日誌中的事件,把中繼日誌中的事件信息一條一條的在本地執行一次,完 成數據在本地的存儲,從而實現將改變反映到它自己的數據(數據重放)。
主從配置注意事項
(1)主從服務器操作系統版本和位數一致;
(2) Master 和 Slave 數據庫的版本要一致;
(3) Master 和 Slave 數據庫中的數據要一致;
(4) Master 開啓二進制日誌,Master 和 Slave 的 server_id 在局域網內必須唯一;
主從配置的簡要步驟
1、Master 上的配置
(1) 安裝數據庫;
(2) 修改數據庫配置文件,指明 server_id,開啓二進制日誌(log-bin);
(3) 啓動數據庫,查看當前是哪個日誌,position 號是多少;
(4) 登錄數據庫,授權數據複製用戶(IP 地址爲從機 IP 地址,如果是雙向主從,這裏的 還需要授權本機的 IP 地址,此時自己的 IP 地址就是從 IP 地址);
(5) 備份數據庫(記得加鎖和解鎖);
(6) 傳送備份數據到 Slave 上;
(7) 啓動數據庫;
以下步驟,爲單向主從搭建成功,想搭建雙向主從需要的步驟:
(1) 登錄數據庫,指定 Master 的地址、用戶、密碼等信息(此步僅雙向主從時需要);
(2) 開啓同步,查看狀態;
2、Slave 上的配置
(1) 安裝數據庫;
(2) 修改數據庫配置文件,指明 server_id(如果是搭建雙向主從的話,也要開啓二進制 日誌 log-bin);
(3) 啓動數據庫,還原備份;
(4) 查看當前是哪個日誌,position 號是多少(單向主從此步不需要,雙向主從需要);
(5) 指定 Master 的地址、用戶、密碼等信息;
(6) 開啓同步,查看狀態。
單向主從環境搭建
安裝數據庫
參考《MySQL之——源碼編譯MySQL8.x+升級gcc+升級cmake(親測完整版)》。
配置Master的my.cnf
[root@liuyazhuang131 ~]# vi /etc/my.cnf
# 在 [mysqld] 中增加以下配置項 # 設置 server_id,一般設置爲 IP server_id=131 # 複製過濾:需要備份的數據庫,輸出 binlog #binlog-do-db=liuyazhuang # 複製過濾:不需要備份的數據庫,不輸出(mysql 庫一般不同步) binlog-ignore-db=mysql # 開啓二進制日誌功能,可以隨便取,最好有含義 log-bin=lyz-mysql-bin ## 爲每個 session 分配的內存,在事務過程中用來存儲二進制日誌的緩存 binlog_cache_size=1M ## 主從複製的格式(mixed,statement,row,默認格式是 statement) binlog_format=mixed # 二進制日誌自動刪除/過期的天數。默認值爲 0,表示不自動刪除。 expire_logs_days=7 # 跳過主從複製中遇到的所有錯誤或指定類型的錯誤,避免 slave 端複製中斷。 # 如:1062 錯誤是指一些主鍵重複,1032 錯誤是因爲主從數據庫數據不一致 slave_skip_errors=1062
複製過濾可以讓你只複製服務器中的一部分數據,有兩種複製過濾:
(1) 在 Master 上過濾二進制日誌中的事件;
(2) 在 Slave 上過濾中繼日誌中的事件。如下:
MySQL 對於二進制日誌 (binlog)的複製類型
(1) 基於語句的複製:在 Master 上執行的 SQL 語句,在 Slave 上執行同樣的語句。MySQL 默 認採用基於語句的複製,效率比較高。一旦發現沒法精確複製時,會自動選着基於行的複製。
(2) 基於行的複製:把改變的內容複製到 Slave,而不是把命令在 Slave 上執行一遍。從MySQL5.0 開始支持。
(3) 混合類型的複製:默認採用基於語句的複製,一旦發現基於語句的無法精確的複製時,就會採用基於行的複製。
重啓Master庫
啓動/重啓 Master 數據庫服務,登錄數據庫,創建數據同步用戶,並授予相應的權限
[root@liuyazhuang131 ~]# service mysql restart
[root@liuyazhuang131 ~]# mysql -uroot -proot
##創建數據同步用戶,並授予相應的權限 mysql> grant replication slave, replication client on *.* to 'repl'@'192.168.209.132' identified by '123456'; Query OK, 0 rows affected (0.00 sec) ## 刷新授權表信息 mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) ## 查看 position 號,記下 position 號(從機上需要用到這個 position 號和現在的日誌文件) mysql> show master status; +----------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +----------------------+----------+--------------+------------------+-------------------+ | lyz-mysql-bin.000001 | 1312 | | mysql | | +----------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
模擬業務數據庫
創建 lyz 庫、表,並寫入一定量的數據,用於模擬現有的業務系統數據庫
create database if not exists lyz default charset utf8 collate utf8_general_ci; use lyz; DROP TABLE IF EXISTS `lyz_user`; CREATE TABLE `lyz_user` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(255) NOT NULL DEFAULT '' COMMENT '用戶名', `pwd` varchar(255) NOT NULL DEFAULT '' COMMENT '密碼', PRIMARY KEY (`Id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用戶信息表'; INSERT INTO `lyz_user` VALUES (1,'yixiaoqun','123456');
實現初始數據一致
爲保證 Master 和 Slave 的數據一致,我們採用主備份,從還原來實現初始數據一致
## 先臨時鎖表 mysql> flush tables with read lock; Query OK, 0 rows affected (0.00 sec) ## 這裏我們實行全庫備份,在實際中,我們可能只同步某一個庫,那也可以只備份一個庫 [root@liuyazhuang131 mysql]# mysqldump -u root -proot lyz > /tmp/lyz.sql [root@liuyazhuang131 mysql]# cd /tmp [root@liuyazhuang131 tmp]# ll | grep lyz.sql -rw-r--r-- 1 root root 2031 Apr 25 01:18 lyz.sql # 注意:實際生產環境中大數據量(超 2G 數據)的備份,建議不要使用 mysqldump 進行 比分,因爲會非常慢。此時推薦使用 XtraBackup 進行備份。 # 解鎖表 mysql> unlock tables; Query OK, 0 rows affected (0.00 sec)
將 Master 上備份的數據遠程傳送到 Slave 上,以用於 Slave 配置時恢復數據
[root@liuyazhuang131 tmp]# scp /tmp/lyz.sql [email protected]:/tmp/lyz.sql The authenticity of host '192.168.209.132 (192.168.209.132)' can't be established. RSA key fingerprint is da:70:7b:d5:0c:16:b3:1a:53:b7:3d:9f:20:01:26:3e. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.209.132' (RSA) to the list of known hosts. [email protected]'s password: lyz.sql
配置Slave庫
接下來處理 Slave(192.168.209.132),配置文件只需修改一項,其餘配置用命令來操作
[root@liuyazhuang132 ]# vi /etc/my.cnf # 在 [mysqld] 中增加以下配置項 # 設置 server_id,一般設置爲 IP server_id=132 # 複製過濾:需要備份的數據庫,輸出 binlog #binlog-do-db=lyz # 複製過濾:不需要備份的數據庫,不輸出(mysql 庫一般不同步) binlog-ignore-db=mysql # 開啓二進制日誌,以備 Slave 作爲其它 Slave 的 Master 時使用 log-bin=lyz-mysql-slave1-bin ## 爲每個 session 分配的內存,在事務過程中用來存儲二進制日誌的緩存 binlog_cache_size = 1M # 主從複製的格式(mixed,statement,row,默認格式是 statement) binlog_format=mixed # 二進制日誌自動刪除/過期的天數。默認值爲 0,表示不自動刪除。 expire_logs_days=7 # 跳過主從複製中遇到的所有錯誤或指定類型的錯誤,避免 slave 端複製中斷。 # 如:1062 錯誤是指一些主鍵重複,1032 錯誤是因爲主從數據庫數據不一致 slave_skip_errors=1062 ## relay_log 配置中繼日誌 relay_log=lyz-mysql-relay-bin ## log_slave_updates 表示 slave 將複製事件寫進自己的二進制日誌 log_slave_updates=1 ##防止改變數據(除了特殊的線程) read_only=1
如果Slave爲其它的Slave的Master時,必須設置bin_log,在這裏,我開啓了二進制日誌,而且顯式的命名(默認名稱爲hostname),但是如果hostname改變則會出現問題。
relay_log配置中繼日誌,log_slave_updates表示slave將複製事件 寫進自己的二進制日誌.當設置log_slave_updates時,你可以讓slave扮演其它slave的master.此時,slave把sql線程執行的事件寫進自己的二進制日誌(binary log)然後,它的slave可以獲取這些事件並執行它。如下圖所示(發送複製事件到其它的Slave):
還原備份數據
保存後重啓MySQL服務,還原備份數據
[root@liuyazhuang132 ~]# service mysql restart Shutting down MySQL. SUCCESS! Starting MySQL.. SUCCESS!
Slave上創建相同庫
[root@liuyazhuang132 ~]# mysql -uroot -proot
mysql> use lyz; Database changed
導入數據
[root@liuyazhuang132 ~]# mysql -uroot -proot lyz < /tmp/lyz.sql [root@liuyazhuang132 ~]# mysql -uroot -proot
mysql> use lyz; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from lyz_user; +----+-----------+--------+ | Id | userName | pwd | +----+-----------+--------+ | 1 | yixiaoqun | 123456 | +----+-----------+--------+ 1 row in set (0.00 sec)
Slave庫添加參數
登錄Slave數據庫,添加相關參數:Master的IP、端口、同步用戶、密碼、position號、讀取哪個日誌文件
change master to master_host='192.168.209.131',master_user='repl',master_password='123456',master_port=3306, master_log_file='lyz-mysql-bin.000001',master_log_pos=1312,master_connect_retry=30;
上面執行的命令的解釋:
- master_host=‘192.168.209.131’ ##Master的IP地址
- master_user=‘repl’ ##用於同步數據的用戶(在Master中授權的用戶)
- master_password=‘123456’ ##同步數據用戶的密碼
- master_port=3306 ##master數據庫服務的端口
- master_log_file=‘lyz-mysql-bin.000001’ ##指定Slave從哪個日誌文件開始讀取複製文件(可在Master上使用show master status查看到日誌文件名)
- master_log_pos=429 ##從哪個POSITION號開始讀
- master_connect_retry=30 #當重新建立主從連接時,如果連接建立失敗,間隔多久後重試,單位爲秒,默認設置爲60秒,同步延遲調優參數。
查看主從同步狀態
show slave status\G;
可看到Slave_IO_State爲空,Slave_IO_Runngin和Slave_SQL_Running是No,表時Slave還是沒有開始複製過程。
開啓主從同步
mysql> start slave;
再次查看同步狀態
#show slave status\G;
主要看以下兩個參數,這兩個參數如果是Yes,就表示數據同步正常
Slave_IO_Running:Yes Slave_SQL_Running:Yes
可查看master和slave上線程的狀態,在master上,可以看到slave的I/O線程創建的連接
Master:mysql>show processlist\G;
1.row爲處理slave的I/O線程的連接。
2.row爲處理MySQL客戶連接線程。
3.row爲處理本地命令行的線程
Slave:mysql>show processlist\G;
1.row爲處理slave的I/O線程的連接。
2.row爲處理MySQL客戶連接線程。
3.row爲處理本地命令行的線程
主從數據複製同步測試
Master: mysql> insert into lyz_user values(2,'test1','123456'); Slave: mysql> start slave;
經過以上配置,在192.168.209.131上對數據庫/表進行增刪改查,創建/刪除數據庫/表都會同步到192.168.209.132數據庫上了。
至此,整個配置過程結束。