Categories
程式開發

MySQL-技術專題-主從復制原理


摘要

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-技術專題-主從復制原理 1

主實例搭建

運行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-技術專題-主從復制原理 2

進入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;

主從復制命令參數說明:查看主從同步狀態:

show slave status G;

從數據庫狀態顯示如下:

MySQL-技術專題-主從復制原理 3

開啟主從同步:

start slave;

查看從數據庫狀態發現已經同步:

MySQL-技術專題-主從復制原理 4

主從復制測試

主從復制的測試方法有很多,可以在主實例中創建一個數據庫,看看從實例中是否有該數據庫,如果有,表示主從復制已經搭建成功。

在主實例中創建一個數據庫mall;

MySQL-技術專題-主從復制原理 5

在從實例中查看數據庫,發現也有一個mall數據庫,可以判斷主從復制已經搭建成功。

MySQL-技術專題-主從復制原理 6