摘要
本文將從MySQL主從復制的原理出發,詳細介紹MySql在Docker環境下的主從復制搭建,以一個主實例和一個從實例實現主從復制為例。
什么是主從復制?
主從復制是指將主數據庫的DDL和DML操作通過二進制日志傳到從數據庫上,然后在從數據庫上對這些日志進行重新執行,從而使從數據庫和主數據庫的數據保持一致。
主從復制的原理
- MySql主庫在事務提交時會把數據變更作為事件記錄在二進制日志Binlog中;
- 主庫推送二進制日志文件Binlog中的事件到從庫的中繼日志Relay Log中,之后從庫根據中繼日志重做數據變更操作,通過邏輯復制來達到主庫和從庫的數據一致性;
- MySql通過三個線程來完成主從庫間的數據復制,其中Binlog Dump線程跑在主庫上,I/O線程和SQL線程跑著從庫上;
- 當在從庫上啟動復制時,首先創建I/O線程連接主庫,主庫隨后創建Binlog Dump線程讀取數據庫事件并發送給I/O線程,I/O線程獲取到事件數據后更新到從庫的中繼日志Relay Log中去,之后從庫上的SQL線程讀取中繼日志Relay Log中更新的數據庫事件并應用,如下圖所示。
主實例搭建
- 運行mysql主實例:
docker run -p 3307:3306 --name mysql-master -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/lib/mysql -v /mydata/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSword=root -d mysql:5.7
- 在mysql的配置文件夾/mydata/mysql-master/conf中創建一個配置文件my.cnf:
touch my.cnf
- 修改配置文件my.cnf,配置信息如下:
[mysqld]## 設置server_id,同一局域網中需要唯一server_id=101 ## 指定不需要同步的數據庫名稱binlog-ignore-db=mysql ## 開啟二進制日志功能log-bin=mall-mysql-bin ## 設置二進制日志使用內存大小(事務)binlog_cache_size=1M ## 設置使用的二進制日志格式(mixed,statement,row)binlog_format=mixed ## 二進制日志過期清理時間。默認值為0,表示不自動清理。expire_logs_days=7 ## 跳過主從復制中遇到的所有錯誤或指定類型的錯誤,避免slave端復制中斷。## 如:1062錯誤是指一些主鍵重復,1032錯誤是因為主從數據庫數據不一致slave_skip_errors=1062
- 修改完配置后重啟實例:
docker restart mysql-master
- 進入mysql-master容器中:
docker exec -it mysql-master /bin/bash
- 在容器中使用mysql的登錄命令連接到客戶端:
mysql -uroot -proot
- 創建數據同步用戶:
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';復制代碼
從實例搭建
- 運行mysql從實例:
docker run -p 3308:3306 --name mysql-slave -v /mydata/mysql-slave/log:/var/log/mysql -v /mydata/mysql-slave/data:/var/lib/mysql -v /mydata/mysql-slave/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
- 在mysql的配置文件夾/mydata/mysql-slave/conf中創建一個配置文件my.cnf:
touch my.cnf
- 修改配置文件my.cnf:
[mysqld]## 設置server_id,同一局域網中需要唯一server_id=102## 指定不需要同步的數據庫名稱binlog-ignore-db=mysql ## 開啟二進制日志功能,以備Slave作為其它數據庫實例的Master時使用log-bin=mall-mysql-slave1-bin ## 設置二進制日志使用內存大小(事務)binlog_cache_size=1M ## 設置使用的二進制日志格式(mixed,statement,row)binlog_format=mixed ## 二進制日志過期清理時間。默認值為0,表示不自動清理。expire_logs_days=7 ## 跳過主從復制中遇到的所有錯誤或指定類型的錯誤,避免slave端復制中斷。## 如:1062錯誤是指一些主鍵重復,1032錯誤是因為主從數據庫數據不一致slave_skip_errors=1062 ## relay_log配置中繼日志relay_log=mall-mysql-relay-bin ## log_slave_updates表示slave將復制事件寫進自己的二進制日志log_slave_updates=1 ## slave設置為只讀(具有super權限的用戶除外)read_only=1
- 修改完配置后重啟實例:
docker restart mysql-slave
將主從數據庫進行連接
- 連接到主數據庫的mysql客戶端,查看主數據庫狀態:
show master status;
- 主數據庫狀態顯示如下:
- 進入mysql-slave容器中:
docker exec -it mysql-slave /bin/bash
- 在容器中使用mysql的登錄命令連接到客戶端:
mysql -uroot -proot
- 在從數據庫中配置主從復制:
change master to master_host='192.168.6.132', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;
- 主從復制命令參數說明: master_host:主數據庫的IP地址; master_port:主數據庫的運行端口; master_user:在主數據庫創建的用于同步數據的用戶賬號; master_password:在主數據庫創建的用于同步數據的用戶密碼; master_log_file:指定從數據庫要復制數據的日志文件,通過查看主數據的狀態,獲取File參數; master_log_pos:指定從數據庫從哪個位置開始復制數據,通過查看主數據的狀態,獲取Position參數; master_connect_retry:連接失敗重試的時間間隔,單位為秒。
- 查看主從同步狀態:
show slave status G;
- 從數據庫狀態顯示如下:
- 開啟主從同步:
start slave;
- 查看從數據庫狀態發現已經同步:
主從復制測試
主從復制的測試方法有很多,可以在主實例中創建一個數據庫,看看從實例中是否有該數據庫,如果有,表示主從復制已經搭建成功。
- 在主實例中創建一個數據庫mall;
- 在從實例中查看數據庫,發現也有一個mall數據庫,可以判斷主從復制已經搭建成功。
作者:macroZheng
鏈接:https://juejin.im/post/5e1daba46fb9a02fb75d5e92