【MySQL主从同步-基于Docker容器】

版本概述:

  • MySQL版本:8.0.29
  • Docker版本:20.10.18
  • Linux:CentOS 7.x

实现目标:

实现MySQL数据库的主从同步,一主一从。

数据库相关

主机IP 容器名 标识 说明
172.17.0.1:33011 mysql-master master 主库
172.17.0.1:33012 mysql-slave slave 从库

主机IP说明:

**情况1:**同一台服务器,不同容器,使用docker0网卡ip即可(通常为172.17.0.1),可通过 ip addr 查看
**情况2:**不同服务器,不同容器,使用服务器的 内网ip/公网ip+端口即可
**注意:**本次为 情况1

准备工作

docker安装

docker安装方式:

  • 在线安装
  • 离线安装

镜像拉取和容器挂载文件夹创建

# mysql8.0.29镜像拉取
docker pull mysql:8.0.29

# 在宿主机创建挂载目录(主库)
mkdir -p /home/docker/mysql/33011/data \
/home/docker/mysql/33011/conf \
/home/docker/mysql/33011/tmp


# 在宿主机创建挂载目录(从库)
mkdir -p /home/docker/mysql/33012/data \
/home/docker/mysql/33012/conf \
/home/docker/mysql/33012/tmp


# 给tmp文件夹 777权限,可读可写(文件夹原有可执行)如果只给666也会变成777
chmod +777 /home/docker/mysql/33011/tmp
chmod +777 /home/docker/mysql/33012/tmp

主库my.conf内容

该文件存放路径:/home/docker/mysql/33011/conf
image.png

[mysqld]
# 禁止域名解析(也包括主机名),可以消除MySQL进行DNS解析的时间,但所有的连接都必须用IP地址方式。
skip-name-resolve=1

# 数据存放位置(绝对路径)
datadir=/var/lib/mysql

# port:服务端口号,默认为 3306
port=3306

# 数据库默认字符集
character_set_server=utf8mb4

# 数据库字符集对应一些排序等规则,注意要和 character-set-server 对应
collation-server=utf8mb4_general_ci

# MySQL 服务的唯一编号,每个 MySQL 服务的 id 需唯一,不可以和从库重复。
server-id=11

# 以下为主从配置

# 启⽤⼆进制⽇志
log-bin=master-bin

# 指定二进制索引文件的路径与名称(这里只指定了名称)
log_bin_index=master-bin.index

# 二进制日过期时间,7天,单位秒,默认是30天(2592000秒)
 binlog_expire_logs_seconds=604800

# 要给从机同步的库(如果不写,默认全部同步)
# binlog-do-db=db01

#不给从机同步的库(多个写多⾏)
#binlog-ignore-db=mysql
#binlog-ignore-db=information_schema
#binlog-ignore-db=performance_schema
#binlog-ignore-db=sys


主库容器启动

docker run -d -p 3306:3306 --name=mysql-master \
-v /home/docker/mysql/3306/data:/var/lib/mysql \
-v /home/docker/mysql/3306/conf/my.cnf:/etc/my.cnf \
-v /home/docker/mysql/3306/tmp:/tmp \
-e MYSQL_ROOT_PASSWORD=xiaolei@1 \
-e TZ=Asia/Shanghai \
mysql:8.0.33

从库my.conf内容

该文件存放路径:/home/docker/mysql/33012/conf
image.png

[mysqld]
# 禁止域名解析(也包括主机名),可以消除MySQL进行DNS解析的时间,但所有的连接都必须用IP地址方式。
skip-name-resolve=1

# 数据存放位置(绝对路径)
datadir=/var/lib/mysql

# port:服务端口号,默认为 3306
port=3306

# 数据库默认字符集
character_set_server=utf8mb4

# 数据库字符集对应一些排序等规则,注意要和 character-set-server 对应
collation-server=utf8mb4_general_ci

# MySQL 服务的唯一编号,每个 MySQL 服务的 id 需唯一。
server-id=12

# 以下为主从配置

# 只读模式,不会影响slave同步复制的功能
read_only = 1
# 指定二进制索引文件的路径与名称(这里只指定了名称)
log_bin_index=master-bin.index

# 以下参数可以避免更新不及时,SLAVE 重启后导致的主从复制出错

# 中继日志名称(给名字就相当于启用了中断日志)
relay-log = slave-relay-bin
# 主服务器I/O⽇志读取、记录及存放索引
relay-log-index = slave-relay-bin.index

# slave同步master的同步位置信息放在哪里,mysql.slave_relay_info表来记录同步的位置信息
# mysql8不需要这两个设置,从mysql8开始移除了这两个配置,默认都是TABLE,加上会有警告
# master_info_repository=TABLE
# slave记录master的状态,mysql.slave_master_info表
# relay_log_info_repository=TABLE

从库容器启动

docker run -d -p 3306:3306 --name=mysql-slave \
-v /home/docker/mysql/3306/data:/var/lib/mysql \
-v /home/docker/mysql/3306/conf/my.cnf:/etc/my.cnf \
-v /home/docker/mysql/3306/tmp:/tmp \
-e MYSQL_ROOT_PASSWORD=xiaolei@1 \
-e TZ=Asia/Shanghai \
mysql:8.0.33

报错:[InnoDB] Unable to create temporary file inside “/tmp”; errno: 13

  1. 清空宿主机data文件内容
  2. 给宿主机tmp文件夹
  • chmod +777 /home/docker/mysql/33011/tmp
  • chmod +777 /home/docker/mysql/33012/tmp

image.png
image.png

主库配置

踩坑一定要区分主从IP:
主库ip是192.168.10.107
从库ip是192.168.10.110
-- 注意:都是在mysql库下的操作
-- 在主库(master)创建从库(slave)登录用户
create user 'userSlave'@'192.168.10.110' identified by 'xiaolei@1';
select user,host from user;

-- 给从库(slave)登录用户权限(任何库任何表)
grant all privileges on *.* to 'userSlave'@'192.168.10.110';

-- 刷新权限变更
flush privileges;

-- 查看主库状态
show master status; 
注意:(主库状态)
  • File中的文件名只要mysql服务重启一次就会变。如果主从未生效请先检查该文件名在从库配置是否正确。
    • 如果不正确从库需要停止同步并且清空同步配置信息。
  • Postition中的数字,只要主库增删改的有事务发生这个数字就会发生改变。从库在第一次连接没有问题的情况下这个数值可以不用再更改不会出什么问题。单词翻译过来是位置的意思,猜测大概记录了从日志哪个位置开始同步吧。

image.png
image.png

从库配置

-- 注意:都是在mysql库下的操作
-- 连接主库(8.0.23以前的命令)
CHANGE MASTER TO 
master_host = '192.168.10.107',
master_port = 33011,
master_user = 'userSlave',
master_password = '123456',
master_log_file = 'master-bin.000005',
master_log_pos = 157,
get_master_public_key=1; -- 如果是mysql8的数据库加上这个可以防止因为密码策略问题导致连接不成功,

-- 连接主库(8.0.23之后的命令)
CHANGE REPLICATION SOURCE TO
source_host='192.168.10.107',
source_port =33011,
source_user='userSlave',
source_password='123456',
source_log_file='master-bin.000005',
source_log_pos=157,
get_master_public_key=1;


-- 启动主从复制
start slave;

-- 查看同步状态
show slave status\G;

命令参数详解

CHANGE MASTER TO命令

  • master_host 主库ip
  • master_port 主库端口号
  • master_user 从库登录主库的用户名
  • master_password 从库登录主库的密码
  • master_log_file 主库的二进制日志文件名(File中的值)
  • master_log_pos 主库二进制日志文件的同步位置(Postition中的值**)**
  • get_master_public_key=1 开启获取主库连接公钥

CHANGE REPLICATION SOURCE TO命令

  • source_host 主库ip
  • source_port 主库端口号
  • source_user 从库登录主库的用户名
  • source_password 从库登录主库的账号密码
  • source_log_file 主库的二进制日志文件名(File中的值)
  • source_log_pos 主库二进制日志文件的同步位置(Postition中的值**)**
  • get_master_public_key=1 开启获取主库连接公钥

报错: Last_Errno:2061,Last_IO_Error 字段值:error connecting to master ‘[email protected]:33011’ - retry-time: 60 retries: 4 message: Authentication plugin ‘caching_sha2_password’ reported error: Authentication requires secure connection.

image.png

问题出现原因:

mysql8开始密码的加密策略由 mysql_native_password 改为 caching_sha2_password。
在MySQL 8.0中,caching_sha2_password 是默认的身份验证插件,安全性更高。
由于 caching_sha2_password 需要公钥所以连接失败
所以解决思路共有两个方向:

  1. 拿到公钥存到本机mysq相应目录下
  2. 改变从库登录用户的加密策略

解决方案1(推荐):增加连接主库参数 get_master_public_key=1

这个参数可以让从库在连接服务器时,拿到主库服务器mysql的公钥

-- 以下操作在从库服务的mysql库
-- 停止主从复制
stop slave;

-- 清空之前的主从复制配置信息
reset slave all;

-- 查看同步状态(这个时候应该是什么都没了)
show slave status;

-- 增加参数 get_master_public_key=1
CHANGE REPLICATION SOURCE TO
source_host='172.17.0.1',
source_port =33011,
source_user='userSlave',
source_password='123456',
source_log_file='master-bin.000005',
source_log_pos=157,
get_master_public_key=1;

解决方案2:修改从库登录用户的加密策略

-- 以下操作在主库的mysql库
-- 修改用户加密策略
ALTER USER 'userSlave'@'172.17.0.1' IDENTIFIED WITH mysql_native_password BY '123456';

-- 刷新权限变更
flush privileges;


-- 分割线
-- 以下操作均为从库mysql库操作
-- 停止主从复制
stop slave;

-- 清空之前的主从复制配置信息
reset slave all;

-- 查看同步状态(这个时候应该是什么都没了)
show slave status;

-- 重新连接即可
CHANGE MASTER TO master_host = '172.17.0.1',
master_port = 33011,
master_user = 'userSlave',
master_password = '123456',
master_log_file = 'master-bin.000005',
master_log_pos = 157;

主从状态检查

主库

在主库查看,若如下图Command字段中出现Binlog Dump字符则表示主从连接成功

-- 查看用户连接列表
show processlist;

image.png

从库

查看同步状态,主要检查图片中四个参数是否如下方图片一只

-- 从库状态
show slave status;

image.png
image.png

主从测试

在主库创建test库和test-table表,查看从库

image.png

操作数据验证

增删改都能同步
image.png
image.png

相关命令

-- 主库
-- 在主库(master)创建从库(slave)登录用户
create user 'userSlave'@'172.17.0.1' identified by '123456';

-- 查看用户登录连接
select user,host from user;

-- 给从库(slave)登录用户权限(任何库任何表)
grant all privileges on *.* to 'userSlave'@'172.17.0.1';

-- 刷新权限变更
flush privileges;

-- 查看主库状态
show master status; 

-- 查看用户连接列表
show processlist;

-- 删除用户,删完要刷新权限
drop user 'userSlave'@'172.17.0.1';

-- 从库
-- 连接主库(8.0.23以前的命令)
CHANGE MASTER TO master_host = '172.17.0.1',
master_port = 33011,
master_user = 'userSlave',
master_password = '123456',
master_log_file = 'master-bin.000005',
master_log_pos = 157,
get_master_public_key=1; -- 如果是mysql8的数据库加上这个可以防止因为密码策略问题导致连接不成功,

-- 连接主库(8.0.23之后的命令)
CHANGE REPLICATION SOURCE TO
source_host='172.17.0.1',
source_port =33011,
source_user='userSlave',
source_password='123456',
source_log_file='master-bin.000006',
source_log_pos=157,
get_master_public_key=1;


-- 启动主从复制
start slave;

-- 查看同步状态
show slave status;


-- 停止主从复制
stop slave;

-- 清空之前的主从复制配置信息
reset slave all;

主库重启后从库该如何重新连接

**前提:**两个数据要一致,不然要导出主库从头来过

-- 主库
-- 查看主库状态,拿到file名字和日志pos位置
show master status; 

-- 帅气分割线

-- 从库
-- 停止主从复制
stop slave;
-- 清空之前的主从复制配置信息
reset slave all;

-- 连接主库
CHANGE REPLICATION SOURCE TO
source_host='172.17.0.1',
source_port =33011,
source_user='userSlave',
source_password='123456',
source_log_file='master-bin.000006',
source_log_pos=157,
get_master_public_key=1;

其他错误

**注意:**一旦主从出现报错,同步就会停止!

报错:Last_Errno:1062, Last_IO_Error :Coordinator stopped because there were error(s) in the worker(s).The most recent failure being: Worker 1 failed executing transaction ‘ANONYMOUS’ at master log master-bin.000005,end_log_pos 4293. See error log and/or performance_schema.replication_applier_status_by_worker tablefor more details about this failure or others, if any.

问题原因:

报错以后有很大一部分原因是因为主从数据不一致导致的

解决方案1(不推荐):清库(简单粗暴)

注意:仅适用于库里没啥数据!!!
这个只需要保证主库和从库数据一致即可,因为是测试,目前的解决方案是两边把数据都删掉,然后从库重新连接主库,但是要注意,主库中的 **Postition **数值这个会发生改变,连接时要重新用命令 show master status; 去看最新的。

解决方案2(推荐):

想办法同步数据库,例如:重新开一个主从关系,将原来的主库数据导入新的主库

错误代码速查

1062:

主键id冲突。从库插入数据,发生唯一性冲突。此时从库已经有相同主键的数据,如果再插入相同主键值的数据则会报错。可以查看主库的改行数据与从库的要插入数据是否一致,如一致则跳过错误,恢复SQL线程,如不一致,则以主库为准,将从库的该行记录删除,再开启复制。

2061:

加密策略不一致。mysql8开始密码的加密策略由 mysql_native_password 改为 caching_sha2_password。
在MySQL 8.0中,caching_sha2_password 是默认的身份验证插件,安全性更高。
由于 caching_sha2_password 需要公钥所以连接失败

猜你喜欢

转载自blog.csdn.net/weixin_42506139/article/details/130802296
今日推荐