引言
MySQL从3.23版本开始提供复制功能,复制主要是指将主数据库上的DDL、DML操作通过日志(Binary Log)的形式传送到从数据库,然后在从数据库上对这些操作再次执行,从而实现从服务器与主服务器的数据同步。
复制过程概述
- 主库将数据变更的操作作为事件记录在
二进制日志(Binary Log)
中 - 主库推送
二进制日志(Binary Log)
的信息到从库的中继日志(Relay Log)
文件中 - 从库根据
中继日志(Relay Log)
的内容更新数据库
系统环境
- CentOS 7.6
- Docker 18.09.6
- MySql 5.6.46
搭建过程
创建MySql主、从容器
Docker如何安装MySql可以参考:Docker安装MySql
Master(主):
1 | docker run -p 4001:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6.46 |
Slave(从):
1 | docker run -p 4002:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6.46 |
配置Master(主)
设置server-id
,打开 Binary Log
将配置文件拷贝出来(注:不同镜像版本的配置文件路径可能不同)
1 | docker cp mysql-master:/etc/mysql/mysql.conf.d/mysqld.cnf mysqld-master.cnf |
在配置文件中添加如下内容:
1 | [mysqld] |
然后将配置文件拷贝回去:
1 | docker cp mysqld-master.cnf mysql-master:/etc/mysql/mysql.conf.d/mysqld.cnf |
重启容器使配置生效
1 | docker restart mysql-master |
创建同步账户
登入主数据库的MySql
1 | docker exec -it mysql-master /usr/bin/mysql -uroot -p123456 |
然后在MySql中分别执行如下命令创建同步用户
1 | mysql> CREATE USER 'slave'@'%' IDENTIFIED BY '123456'; |
其中slave
为账户名,123456
为密码。
锁定主数据库
锁定主数据库,只允许读取不允许写入,这样做的目的是为了防止搭建过程中有新数据插入,导致主、从数据库中的数据不一致。
1 | mysql> flush tables with read lock; |
随便插入或更新一条数据,如果有如下提示说明锁库成功
1 | ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock |
查看主数据库状态
在Master的MySql执行show master status;
1 | mysql> show master status; |
File
和Position
字段的值后面将会用到,在后面的操作完成之前,需要保证Master库
不能做任何操作,否则将会引起File
和Position
字段的值变化。
配置Slave(从)
将配置文件拷贝出来
1 | docker cp mysql-slave:/etc/mysql/mysql.conf.d/mysqld.cnf mysqld-slave.cnf |
在配置文件中添加如下内容:
1 | [mysqld] |
然后将配置文件拷贝回去:
1 | docker cp mysqld-slave.cnf mysql-slave:/etc/mysql/mysql.conf.d/mysqld.cnf |
重启容器使配置生效
1 | docker restart mysql-slave |
主库已有数据的处理(如无数据可跳过这步)
在实际情况下,主库往往已经是在生产环境跑了一段时间,里面已经有许多数据,如果这些数据不能丢弃,那么我们需要先将这部分数据导入到从库中然后再认主。
备份主数据库
要确保在开始备份之前主数据库已经锁定,防止备份过程中数据发生变化,下面的备份命令仅供参考,只要是能正确通过mysqldump
备份出主数据的数据就行
1 | docker exec mysql-master /usr/bin/mysqldump -uroot -p123456 -A > backup.sql |
-A
表示要备份所有数据库,mysqldump具体用法可以参考 mysqldumpmysqldump
在容器中的路径可以通过在容器中执行whereis mysqldump
确定
将备份数据导入到从数据库
将主数据库的备份数据拷贝到从数据库的容器中
1 | docker cp backup.sql mysql-slave:/tmp/ |
登录从数据库的MySql
1 | docker exec -it mysql-slave /usr/bin/mysql -uroot -p123456 |
在MySql中执行如下命令来恢复数据
1 | source /tmp/backup.sql |
如果在备份主数据库的时候指定了数据库(比如指定了test
数据库),那么导入数据的时候可能会报错
1 | Warning: Using a password on the command line interface can be insecure. |
这是因为从数据库没有名字为test
的数据库,我们需要创建一个,登入从数据库的MySql,执行命令CREATE DATABASE test;
,然后我们再次导入数据即可成功
获取主数据库的IP地址
命令如下
1 | docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-master |
执行结果
1 | [root@172 temp]# docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-master |
认主
登录从数据库的MySql
1 | docker exec -it mysql-slave /usr/bin/mysql -uroot -p123456 |
建立主从链接
1 | mysql> change master to |
命令说明:master_host
:Master的地址master_port
:Master的端口号,指的是容器的端口号master_user
:用于数据同步的用户master_password
:用于同步的用户的密码master_log_file
:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File
字段的值master_log_pos
:从哪个 Position 开始读,即上文中提到的 Position
字段的值master_connect_retry
:如果连接失败,重试的时间间隔,单位是秒,默认是60秒
开启主从同步
1 | mysql> start slave; |
查看主动复制状态
1 | mysql> show slave status \G; |
如果Slave_IO_Running
和 Slave_SQL_Running
都是Yes
,说明主从复制已经开启。
主从复制排错
使用start slave
开启主从复制后,Slave_IO_Running
一直是Connecting
状态,如下:
1 | Slave_IO_Running: Connecting |
则说明主从复制一直处于连接状态,这种情况一般是下面几种原因造成的,我们可以根据 Last_IO_Error
提示予以排除:
- 网络不通:检查IP、端口、防火墙
- 密码不对:检查用户、密码是否正确;权限授予是否正确;授予完权限后是否有执行
flush privileges;
- pos 不对:检查Master的
Position
解锁主数据库
登入主数据库的MySql
1 | docker exec -it mysql-master /usr/bin/mysql -uroot -p123456 |
解锁
1 | mysql> unlock tables; |
测试验证
测试验证就比较简单了,我们可以在Master中随便填充点数据,然后看Slave中是否有对应的变化就可以了。