MySQL 主从复制(0.5)
1、概述
MySQL主从复制是一个异步的复制过程,底层是基于MySQL数据库自带的二进制日志
功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制然后再解析日志并应用到自身,最终实现从库的数据和主库的数据保持一致。MySQL主从复制是MySQL数据库自带功能,无需借助第三方工具。
主从复制可以缓解单台数据库的访问压力,除此之外,当主库或从库发生损毁时,另一个数据库可以作为备份恢复原有数据,提高了安全性。
2、复制过程
MySQL复制过程分成三步:
- master将改变记录到二进制日志(binary log)
- slave:将master的binary log拷贝到它的中继日志(relay log)
- s1ave重做中继日志中的事件,将改变应用到自己的数据库中
一、Docker 实现主从复制
- 拉取镜像(略)
主服务器
- 新建主服务器容器实例3307
docker run --name mysql-master \
-p 3307:3306 \
-e MYSQL_ROOT_PASSWORD=1234 \
--privileged=true \
-v /mydata/mysql-master/log:/var/log/mysql \
-v /mydata/mysql-master/data:/var/lib/mysql \
-v /mydata/mysql-master/conf:/etc/mysql \
-d mysql:5.7
- 进入/mydata/mysql-master/conf目录下新建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
- 修改配置后重启master实例
docker restart mysql-master
- 进入mysql-master容器
docker exec -it mysql-master /bin/bash
mysql -uroot -proot
- master容器实例内创建数据同步用户
CREATE USER 'slave'@'%' IDENTIFIED BY '1234';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
从服务器
- 新建从服务器容器实例3308
docker run -d -p 3308:3306 --privileged=true \
-v /mydata/mysql-slave/log:/var/log/mysql \
-v /mydata/mysql-slave/data:/var/lib/mysql \
-v /mydata/mysql-slave/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=1234 \
--name mysql-slave mysql:5.7
- 进入/mydata/mysql-slave/conf目录下新建my.cnf
## 设置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
- 重启slave实例
docker restart mysql-slave
其他操作
- 主数据库中查看主从同步状态
show master status;
- 进入mysql-slave容器
docker exec -it mysql-slave /bin/bash
mysql -uroot -proot
- 从数据库中配置主从复制
change master to master_host='宿主机ip', master_user='slave', master_password='1234', master_port=3307, master_log_file='mall-mysql-bin.000004', master_log_pos=617, master_connect_retry=30;
参数说明
- master_host:主数据库的IP地址;
- master_port:主数据库的运行端口;
- master_user:在主数据库创建的用于同步数据的用户账号;
- master_password:在主数据库创建的用于同步数据的用户密码;
- master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
- master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
- master_connect_retry:连接失败重试的时间间隔,单位为秒。
- 从数据库中查看主从同步状态
show slave status \G;
- 从数据库中开启主从同步
start slave;
发现已同步
主从测试
❗注:中文无法插入,修改编码(未解决)后,一定要重新建库建表测试。
建库 > 建表 > 插入数据,查看库状态。
遇到的问题:
Docker ERROR: mysqld failed while attempting to check config
stackoverflow看到一个与这个问题看似无关的答案
意思差不多是,docker命令是对(指令的)顺序敏感的;
到底是怎么回事呢,这里说明一下:
这里对于docker命令,有个小细节就是:
docker ${args_to_docker} run ${args_to_run} image_ref ${cmd_in_container}
比如-e是向容器设置环境变量参数、-p是指端口映射
这两项应该是作用于我们run命令的参数,是必须放在run之后,IMAGE_ID之前设置;
如果像上面的那样顺序,就会被mysql容器内部当成要给当前mysql服务设置的参数,mysql当然是不认识它们的,所以才会报错!
❗建议将-d写到最后。
为什么-d 写dao run 后无报错,写道最后会报错?
即运行容器后立刻退出:Exit(1)
无报错
docker run -d -p 3308:3306 --privileged=true \
-v /mydata/mysql-slave/log:/var/log/mysql \
-v /mydata/mysql-slave/data:/var/lib/mysql \
-v /mydata/mysql-slave/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=1234 \
--name mysql-slave mysql:5.7
报错
docker run --name mysql-master \
-p 3307:3306 \
-e MYSQL_ROOT_PASSWORD=root \
--privileged=true \
-v /mydata/mysql-master/log:/var/log/mysql \
-v /mydata/mysql-master/data:/var/lib/mysql \
-v /mydata/mysql-master/conf:/etc/mysql \
-d mysql:5.7