本文将从MYSQL主从复制原理出发,详细介绍MYSQL在Docker环境下的主从复制搭建,以一个主实例和一个从实例实现主从复制为例。
Docker简单使用教程:https://vuepress.mirror.docker-practice.com
本文参考:https://blog.csdn.net/qq_41345773/article/details/105560281
本文主要记录自己学习实践过程
什么是MYSQL主从复制?
MySQL主从复制是指数据可以从一个主数据库服务器主节点复制到一个或多个从节点。MySQL采用异步复制方式,这样从节点不用访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。
为什么需要主从复制?
随着系统中业务访问量的增大,如果是单机部署数据库,就会导致I/O访问频率过高。有了主从复制,增加多个数据节点,将负载分布在多个从节点上,降低单机磁盘I/O访问的效率,提高单个机器的I/O性能。
一般会让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
从库可以实时从主库进行复制,这样可以做数据的热备。
主从复制原理
- MYSQL主库在事务提交时会把数据变更作为事件记录在二进制日志binlog中;
- 主库推送二进制日志文件binlog中的事件到从库的中继日志Relay Log中,之后从库根据中继日志做数据变更操作,通过逻辑复制来达到主库和从库一致性。;
- MySQL通过三个线程来完成主从库间的数据复制,其中Binlog Dump线程跑在主库上,I/O线程和SQL线程跑在从库上。
- 当在从库上启动复制时,首先创建I/O线程连接主库,主库随后创建Binlog Dump线程读取数据库事件并发送给I/O线程,I/O线程获取到事件数据后更新到从库的中继日志Relay Log中去,之后从库上的SQL线程读取中继日志Relay Log中更新的数据库事件并应用,如下图所示。
下面开始使用Docker搭建MySQL主从复制一主一从实例,这里我采用的腾讯云的Docker镜像环境CentOS8.2-Docker20-VSlJ,非常方便,不需要自己再去安装Docker环境和配置镜像加速。
主实例搭建
1.拉取镜像,查看拉取到的镜像
#拉取镜像
docker pull mysql:5.7
#查看镜像
docker images
2.运行mysql主实例,端口映射为3316,命名为mysql-master2:
docker run -p 3316:3306 --name mysql-master2 \
-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
ec4ef85b0f58f16817b1e519ef60e080bfb471338c64bfd4878bf797665565d6
docker ps -a
通过docker ps -a可以查看当前运行的容器,可以看到mysql-master2主实例在运行中
在启动容器时,对容器中mysql的配置文件夹映射到了宿主机下的文件夹中,进入到宿主机下的文件夹中,创建一个配置文件my.cnf。(注意名称是否正确),这里我在创建文件的时候,有权限不够不允许创建文件的提示,所以对conf目录设置了权限。
#设置目录权限
sudo chmod 777 conf
#进入conf目录下
cd conf
#创建文件
touch my.cnf
#修改文件
vim 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
修改完配置后,需要重启实例:
[lighthouse@VM-20-17-centos mysql-master]$ docker restart mysql-master2
mysql-master2
进入mysql-master2容器中:
[lighthouse@VM-20-17-centos mysql-master]$ docker exec -it mysql-master2 bash
root@ec4ef85b0f58:/#
在容器中使用MySQL的登录命令连接到客户端:
[lighthouse@VM-20-17-centos mysql-master]$ docker exec -it mysql-master2 bash
root@ec4ef85b0f58:/# mysql -uroot -proot
可以发现连接进入到了数据库:
创建数据库同步用户:
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
这个时候把云服务器的防火墙打开后,就可以用Navicat连接上了,如图:
从实例搭建
运行mysql从实例,端口映射为3317,命名为mysql-slave2:
docker run -p 3317:3306 --name mysql-slave2 \
-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
在宿主机目录/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-slave2
将主从数据库进行连接
- 连接到主数据库的mysql客户端,查看主数据库状态:
show master status;
主数据库显示状态如下:
进入mysql-slave2容器中,连接到mysql:
[lighthouse@VM-20-17-centos ~]$ docker exec -it mysql-slave2 bash
root@40ddedfd2ddc:/# mysql -uroot -proot
mysql>
在从数据库中配置主从复制:
mysql> change master to master_host='10.0.20.17', master_user='slave', master_password='123456', master_port=3316, master_log_file='mall-mysql-bin.000002', master_log_pos=371, master_connect_retry=30;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
查看主从同步状态:
mysql> show slave status \G;
开启主从同步:
mysql> start slave;
主从复制测试
通过Navicat连接master、slave数据库,可以看到test表中没有数据
现在像mysql-master2中的test表中插入一条数据
打开mysql-slave2数据库的test表中发现数据已同步过去:
到此,完成了MySQL主从复制一主一从的实例搭建。