在阅读本文前假定您已具备如下知识:
- 熟悉Linux的基本使用
- 熟悉vi/vim的基本操作
- 熟悉Docker的基本操作
- 具备MySQL基本知识
本文操作环境
系统:CentOS Linux release 8.0.1905 (Core)
Docker版本:Docker-CE 19.03.5
账户:root
MySQL主从复制原理
主数据库的每次操作都会记录在其二进制日志(Binlog)中,从库的I/O线程连接到主库中读取主库的二进制日志,并将文件内容写入到从库本地的中继日志(Relay Log)中,然后从库的SQL线程会根据中继日志中的内容执行SQL语句以实现数据复制。
MySQL主从复制用途
- 数据备份
- 读写分离
基于Docker搭建MySQL主从同步
这里使用两台服务器来搭建MySQL主从同步架构(当然只使用一台服务器也是可以的,通过监听不同的端口来模拟多台MySQL服务器,但是这样就失去了数据备份的意义),两台服务器地址如下:
master:master.mysql.devzhou.cn
slave:slave.mysql.devzhou.cn
前提条件
- 两台服务器上都已经安装好Docker环境
- 两台服务器之间能互相进行网络通信
- 两台服务器的防火墙都已经开放MySQL端口(TCP:3306)
- 两台服务器均能正常访问互联网以便于从Docker Hub拉取MySQL镜像
-
创建MySQL配置文件及数据存储目录
在两台服务器上均执行如下命令以创建配置文件和数据存放目录
mkdir -p /data/mysql/{conf,data}
-
编写主数据库配置文件
在主节点服务器上创建主数据库配置文件
vi /data/mysql/conf/my.cnf
写入以下内容
[mysqld]
## 设置server_id,注意要唯一
server_id=100
## 复制过滤:不同步mysql库
binlog-ignore-db=mysql
## 开启binlog
log-bin=replicas-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
-
启动主数据库
这里使用的是MySQL 5.7版本,如要使用8.x版本,则把镜像换成mysql:8
即可
docker run -d -p 3306:3306 -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/data:/var/lib/mysql --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
警告
:切勿在生产环境下使用简单root密码,这里只是为了演示方便
-
创建同步用户
进入MySQL主库容器
docker exec -it mysql-master /bin/bash
连接到MySQL
root@50ba8106b6ce:/# mysql -u root -p
创建同步用户 slave
mysql> CREATE USER 'slave'@'%' IDENTIFIED BY 'slave';
授予 slave
用户同步权限
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
-
从库配置
在从节点服务器上创建从库配置文件
vi /data/mysql/conf/my.cnf
写入配置文件内容,除了server_id和主库配置不同之外,其余配置均相同
[mysqld]
## 设置server_id,注意和主库不同
server_id=101
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
## 开启二进制日志功能,可以随便取,最好有含义(关键就是这里了)
log-bin=replicas-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
-
启动从数据库
docker run -d -p 3306:3306 -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/data:/var/lib/mysql --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
注意
:从库要和主库使用的MySQL版本保持一致,如果主库用的8.x版本,从库也必须使用8.x版本
-
查看主库的binlog状态
在主库执行下面的SQL查看binlog状态
mysql> SHOW MASTER STATUS;
结果如下,记录下File
和Position
的值
+---------------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------------+----------+--------------+------------------+-------------------+
| replicas-mysql-bin.000003 | 617 | | mysql | |
+---------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
-
进入MySQL从库容器
docker exec -it mysql-slave /bin/bash
登录到MySQL
root@eb9b2fe2aa01:/# mysql -u root -p
执行如下的SQL
mysql> change master to master_host='master.mysql.devzhou.cn', master_user='slave', master_password='slave', master_port=3306, master_log_file='replicas-mysql-bin.000003', master_log_pos=617, master_connect_retry=30;
参数解释:
master_host: 主节点服务器的地址
master_user: 用于同步的用户用户名
master_password: 用于同步的用户密码
master_port: 主节点MySQL端口
master_log_file:主节点bin-log名称,也就是上面File字段的值
master_log_pos: 复制位置,也就是上面Position字段的值
注意:
File
和Position
的值每个人的可能都不一样,请替换成自己对应的值
在从库执行SQL,查看从库的状态
mysql> SHOW SLAVE STATUS\G;
显示如下
可以看到Slave_IO_Running
和Slave_SQL_Running
状态都是NO,说明同步线程没有运行
在从库执行以下SQL开始同步
START SLAVE;
再次查看
mysql> SHOW SLAVE STATUS\G;
看到Slave_IO_Running
和Slave_SQL_Running
状态变成了YES,说明同步线程已经开始运行
-
测试
在主库新建一个数据库
CREATE DATABASE devzhou_test_db;
在从库查看
SHOW DATABASES;
输出如下,说明已经同步过来了
+--------------------+
| Database |
+--------------------+
| information_schema |
| devzhou_test_db |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
Q.E.D.
Comments | 9 条评论