创建宿主机 Docker 容器挂载目录
mkdir -p /var/lib/mysql/master1/conf
mkdir -p /var/lib/mysql/master1/data
mkdir -p /var/lib/mysql/slave1/conf
mkdir -p /var/lib/mysql/slave1/data
创建 MySQL 主从配置文件
创建主库配置文件(宿主机路径为 /var/lib/mysql/master1/conf/my.cnf):
[mysqld]
character-set-server = utf8
lower-case-table-names = 1
# 主从复制,主机配置,主服务器唯一ID
server-id = 1
# 启用二进制日志
log-bin=mysql-bin
# 设置logbin格式
binlog_format = STATEMENT
创建从库配置文件(宿主机路径:/var/lib/mysql/slave1/conf/my.cnf):
[mysqld]
character-set-server = utf8
lower-case-table-names = 1
# 主从复制,从机配置,从服务器唯一ID
server-id = 2
# 启用中继日志
relay-log = mysql-relay
授权文件夹:
chmod -R 777 /var/lib/mysql
需要注意的是,主从的 my.cnf 文件权限不能为 777,否则 my.cnf 文件无法在容器内生效,在登陆 Docker 容器内的 MySQL 时会提示:mysql: [Warning] World-writable config file '/etc/mysql/my.cnf' is ignored。解决办法是修改宿主机上主从的 my.cnf 权限为更低的 644:
chmod 644 /var/lib/mysql/master1/conf/my.cnf
chmod 644 /var/lib/mysql/slave1/conf/my.cnf
Docker 容器启动命令
由于本人 MySQL 的 Docker 镜像采用的是 mysql:8.0,默认的 data 路径为 /var/lib/mysql,默认的 my.cnf 文件路径为 /etc/mysql/my.cnf,故配置如下 docker 启动命令。
MySQL 主库:
docker run --name=mysql-master-1 \
--privileged=true \
-p 8808:3306 \
-v /var/lib/mysql/master1/data/:/var/lib/mysql \
-v /var/lib/mysql/master1/conf/my.cnf:/etc/mysql/my.cnf \
-v /var/lib/mysql/master1/mysql-files/:/var/lib/mysql-files/ \
-e MYSQL_ROOT_PASSWORD=xxxxxx \
-d mysql:8.0 --lower_case_table_names=1
MySQL 从库:
docker run --name=mysql-slave-1 \
--privileged=true \
-p 8809:3306 \
-v /var/lib/mysql/slave1/data/:/var/lib/mysql \
-v /var/lib/mysql/slave1/conf/my.cnf:/etc/mysql/my.cnf \
-v /var/lib/mysql/slave1/mysql-files/:/var/lib/mysql-files/ \
-e MYSQL_ROOT_PASSWORD=xxxxxx \
-d mysql:8.0 --lower_case_table_names=1
MySQL 主从同步脚本
MySQL 主库执行脚本:
# 创建用户,设置主从同步的账户名
create user 'live-slave'@'%' identified with mysql_native_password by '12345678';
# 授权
grant replication slave on *.* to 'live-slave'@'%';
# 刷新权限
flush privileges;
# 查询server_id值
show variables like 'server_id';
# 也可临时(重启后失效)指定server_id的值(主从数据库的server_id不能相同)
set global server_id = 1;
# 查询Master状态,并记录File和Position的值,这两个值用于和下边的从数据库中的change那条sql中的master_log_file,master_log_pos参数对齐使用
show master status;
# 重置下master的binlog位点
reset master;
可以从 show master status 获得主库当前的 File 和 Position 信息,例如 File 为 mysql-bin.000001,Position 为 157,用于从库 master_log_file 和 master_log_pos 的设置。
MySQL 从库执行脚本:
# 查询server_id值
show variables like 'server_id';
# 也可临时(重启后失效)指定server_id的值(主从数据库的server_id不能相同)
set global server_id = 2;
# 若之前设置过同步,请先重置
stop slave;
reset slave;
# 设置主数据库
change master to master_host='172.20.10.5',master_port=8808,master_user='live-slave',master_password='12345678',master_log_file='mysql-bin.000001',master_log_pos=157;
# 开始同步
start slave;
# 查询Slave状态
show slave status;
# 若出现错误,则停止同步,重置后再次启动
stop slave;
reset slave;
start slave;
根据主库的 IP、端口等信息,设置从库的主数据库,同时设置 master_log_file 和 master_log_pos 为上一步从主库获取的 File 和 Position 值。
MySQL 主从同步状态判断
开始同步后,若执行 show slave status; 查询从库状态时,若满足以下条件,则表示主从同步正常:
- Slave_IO_Running 显示为 Yes
- Slave_SQL_Running 显示为 Yes
在此之上,比较以下两对值,若均一致,则表示主从同步完成且一致:
- 主库 ( File , Position ) = 从库 ( Master_Log_File , Read_Master_Log_Pos )
- 从库 ( Master_Log_File , Read_Master_Log_Pos ) = 从库 ( Relay_Master_Log_File , Exec_Master_Log_Pos )
其中:
- 主库 ( File , Position ) 记录了主库 binlog 的位置。
- 从库 ( Master_Log_File , Read_Master_Log_Pos ) 记录了从库 IO 线程当前正在接收的二进制日志事件在主库 binlog 中的位置,如果小于 ( File , Position ),则表示 IO 线程存在延迟。
- 从库 ( Relay_Master_Log_File, Exec_Master_Log_Pos ) 记录了从库 SQL 线程当前正在执行的二进制日志事件在主库 binlog 的位置,如果小于 ( Master_Log_File, Read_Master_Log_Pos ),则表示 SQL 线程存在延迟。