Docker 搭建 MySQL 主从复制(一主一从)
使用Docker来搭建MySQL主从复制是很快捷的,只需要拉取镜像,启动2个MySQL容器就行了。而且容器是互相独立的,每个容器都有自己的IP。
基于 Docker 来搭建 MySQL 的主从复制的步骤大致如下:
- 拉取MySQL的镜像(本次使用5.7,如果没有安装虚拟机和Docker的话,请自行安装好)
- 启动两个MySQL的容器,一主一从;
- 配置主服务器(Master)
- 配置从服务器(Slave)
- 完成Master和Slave链接,开始主从复制
- 测试配置是否成功
1、拉取镜像
拉取镜像:docker pull mysql:5.7
查看镜像:docker images
2、启动MySQL容器
2.1 命令启动两个MySQL
主Master:
docker run -d -p 3307:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
命令解释:通过镜像 mysql:5.7 启动一个名为 mysql-master 的 MySQL 服务器,端口号是3306,映射的宿主机端口号是3307,root 账号密码是123456
从Slave:虚拟机的3308映射到容器的3306端口
docker run -d -p 3308:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
命令解释:通过镜像 mysql:5.7 启动一个名为 mysql-slave 的 MySQL 服务器,端口号是3306,映射的宿主机端口号是3308,root 账号密码是123456
启动完成之后,可以通过命令:docker ps 查看运行中的容器,docker ps -a 可以查看所有的容器,包括停止的。
2.2 查看两个容器的IP
命令:
docker inspect --format='{{.NetworkSettings.IPAddress}}' (容器名称|容器ID)
查看主Master的IP:
docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-master
#我这里的Master的IP是:172.17.0.4 这个值在后面要用到
查看从Slave的IP:
docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-slave
#我这里的Master的IP是:172.17.0.5
3、配置主服务器(Master)
首先,执行下面的命令,进入到 Master 服务器:
docker exec -it mysql-master /bin/bash
#这里的mysql-master是容器的名称,也可以是容器的ID,几乎所有的命令,名称和ID可以互用
service mysql status
#进入容器之后,可以使用该命令查看mysql的运行状态和版本,版本是 5.7.30。搭建主从复制时,最好保持版本的一致。
[email protected]:/# service mysql status
[info] MySQL Community Server 5.7.30 is running.
其次,修改配置文件:my.cnf,在/etc/mysql下面,有一个mysql的配置文件my.cnf,
[email protected]:/etc/mysql# cd /etc/mysql/
[email protected]:/etc/mysql# ls
conf.d my.cnf my.cnf.fallback mysql.cnf mysql.conf.d
执行命令,修改配置:
vi my.cnf
执行之后,可能会报错:bash: vi: command not found
此时就需要执行:apt-get install vim 命令安装vim,如果在这个过程中出现下面的错误:
Building dependency tree
Reading state information... Done
E: Unable to locate package vim
就需要执行:apt-get update ,成功之后,然后再执行 apt-get install vim 命令安装vim
一切就绪之后,在my.cnf文件中添加下面的配置:
#[mysqld]这个不能漏掉了
[mysqld]
## 设置server_id,一般设置为IP,同一局域网内注意要唯一
server_id=1
## 开启二进制日志功能,可以随便取,最好有含义(关键就是这里了)
log-bin=mysql-bin
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
## 为每个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服务:
配置完成之后,需要重启mysql服务使配置生效。使用service mysql restart完成重启。
service mysql restart
重启mysql服务时会使得docker容器停止,我们还需要docker start mysql-master启动容器。
下一步在Master数据库创建数据同步用户,授予用户 slave REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据。
docker exec -it mysql-master /bin/bash 进入容器
mysql -uroot -p123456 登录mysql
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
4、配置从服务器(Slave)
其他命令操作和Master是一样的,它的主要目的也是为了修改my.cnf配置文件,配置文件修改如下:
[mysqld]
## 设置server_id,一般设置为IP,注意要唯一
server_id=2
## relay_log配置中继日志
relay_log=mysql-relay-bin
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave1-bin
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql
## 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## 防止改变数据(除了特殊的线程)
read_only=1
也只有前面三个配置是必须配置的,其他可以不用配置
配置完成后,同样要重启:service mysql restart,同样要重启容器:docker start mysql-slave
5、完成Master和Slave链接,开始主从复制
注意:需要保证 Master 和 Slave 除了不同步的数据库,其他数据库的数据要一致。
5.1 Master主服务器操作
在主Master,首先进入容器,然后进入Mysql数据库
执行命令:show master status;
[[email protected] ~]# docker exec -it mysql-master /bin/bash
[email protected]:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.30-log MySQL Community Server (GPL)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 617 | | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql>
**记录下 File 和 Position 字段的值,后面会用到。**在后面的操作完成之前,需要保证Master库不能做任何操作,否则将会引起状态变化,File和Position字段的值变化。
5.2 Slave从服务器操作
在主Master,首先进入容器,然后进入Mysql数据库
执行命令:
change master to master_host='172.17.0.4', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 617, master_connect_retry=30;
# master_host: Master 的IP地址
# master_user: 在 Master 中授权的用于数据同步的用户
# master_password: 同步数据的用户的密码
# master_port: Master的数据库的端口号,不是宿主机映射的端口号
# master_log_file: 指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
# master_log_pos: 从哪个 Position 开始读,即上文中提到的 Position 字段的值
# master_connect_retry: 当重新建立主从连接时,如果连接失败,重试的时间间隔,单位是秒,默认是60秒。
[[email protected] ~]# docker exec -it mysql-slave /bin/bash
[email protected]:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.30-log MySQL Community Server (GPL)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> change master to master_host='172.17.0.4', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 617, master_connect_retry=30;
在 Slave 的 MySQL 终端执行查看主从同步状态:
show slave status \G;
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.4
Master_User: slave
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 617
Relay_Log_File: edu-mysql-relay-bin.000008
Relay_Log_Pos: 367
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mybatis_plus
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 617
Relay_Log_Space: 744
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: d6ae1b03-9f26-11ea-80e8-0242ac110004
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
SlaveIORunning 和 SlaveSQLRunning 是No,表明 Slave 还没有开始复制过程。相反 SlaveIORunning 和 SlaveSQLRunning 是Yes表明已经开始工作了,因为我已经运行过了,所以我的显示的都是 Yes。
执行以下命令,开始开启主从同步:
start slave;
正常情况下,执行这个命令之后,SlaveIORunning 和 SlaveSQLRunning 就是Yes了。
slave stop; 关闭主从同步
reset slave; 重置主从同步
5.3 主从复制排错
使用
start slave
开启主从复制过程后,如果SlaveIORunning一直是Connecting,则说明主从复制一直处于连接状态,这种情况一般是下面几种原因造成的,我们可以根据 Last_IO_Error提示予以排除:
-
网络不通
检查ip,端口
-
密码不对
检查是否创建用于同步的用户和用户密码是否正确
-
pos不对
检查Master的 Position
6、测试主从同步
可以在主Master中创建数据库,然后新建数据库表,往表里插入数据,修改数据,删除数据等这些操作都会同步到从库中。
注意:
- 操作从库,比如新增数据,修改数据等不会同步到主库的,主从复制是单向的,主库会影响从库,从库不会影响主库。
- 查询操作是不会同步的。
下一次讲解:SpringBoot ,MyBatis Plus 项目中,怎么通过代码实现主从复制的读写分离操作。