参考文章:
主从数据库复制+Springboot项目中配置主从数据库读写分离
1.0、准备
先准备两个MySQL容器,最好是同版本的
# 主节点对外映射端口3307
sir-2:~ x$ docker run -p 3307:3306 --name master_mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.22
315e1ecad855b5bbe1589a5f51351b665c8c80efacede7fcff871cea7c16e7dd
# 从节点对外映射端口3308
sir-2:~ x$ docker run -p 3308:3306 --name slave_mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.22
71c3bb3bcdbf7c67aa19486e112d0a1b19364557b592e55703718f6bb33e3c24
sir-2:~ x$
可使用docker ps
检查两个容器是否正确运行。
sir-2:~ x$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
71c3bb3bcdbf mysql:8.0.22 "docker-entrypoint.s…" 1 minutes ago Up 40 minutes 33060/tcp, 0.0.0.0:3308->3306/tcp, :::3308->3306/tcp slave_mysql
315e1ecad855 mysql:8.0.22 "docker-entrypoint.s…" 2 minutes ago Up 20 minutes 33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp master_mysql
sir-2:~ x
设置主从为相同时区,并尽量使用相同时间服务器,避免时间不一致造成问题。
2.0、配置主节点
-
进入容器交互环境,并安装vim以编辑my.cnf。
# 进入master_mysql的终端交互环境 sir-2:~ x$ docker exec -it master_mysql /bin/bash # 设置时区 root@315e1ecad855:/# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime root@315e1ecad855:/# echo 'Asia/Shanghai' >/etc/timezone # 更新apt-get root@315e1ecad855:/# apt-get update Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB] Get:2 http://repo.mysql.com/apt/debian buster InRelease [21.5 kB] ... # apt-get安装vim,对所有交互询问都回复yes root@315e1ecad855:/# apt-get install vim -y Reading package lists... Done Building dependency tree ... # vim编辑my.cnf root@315e1ecad855:/# vim /etc/mysql/my.cnf
-
my.cnf
在[mysqld]
分区下添加下面内容后保存,exit退出容器交互环境。# 同一局域网内唯一ID,如果不配置或置为0,表示主节点拒绝来只从节点的连接。 server-id=1 # 二进制日志功能,保存数据库的所有操作,从节点会同步这些二进制日志 log-bin=mysql-bin # 二进制日志格式,有row、statement、mixed三种格式, # row指的是把改变的内容复制过去,而不是把命令在从服务器上执行一遍, # statement指的是在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。 # mixed指的是默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。 # binlog-format=ROW # 设置需要同步的库,有多个就用逗号隔开,也可以不指定,直接同步所有的库 # binlog-do-db=test # 设置忽略的库 # binlog-ignore-db=information_schema
-
重启容器
sir-2:~ x$ docker restart master_mysql master_mysql sir-2:~ x$
-
查看server-id是否已经修改
# 连接mysql sir-2:~ x$ mysql -h127.0.0.1 -uroot -p123456 -P3307 mysql: [Warning] Using a password on the command line interface can be insecure. ... # 查询 mysql> show variables like 'server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 1 | +---------------+-------+ 1 row in set (0.01 sec) mysql>
-
查看二进制日志文件,记住File和Position字段的内容,配置从节点需要这些数据。
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 156 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) mysql>
-
创建数据同步用户,并赋予replication slave和replication client权限。
# 创建数据同步用户 mysql> create user 'slave'@'%' identified by '123456'; Query OK, 0 rows affected (0.01 sec) # 为数据同步用户添加权限 # grant 赋权命令 # *.*当前用户对所有库和表的相应操作权限 # 'slave'@'%'权限赋给slave用户,所有IP都能连接 mysql> grant replication slave, replication client on *.* to 'slave'@'%'; Query OK, 0 rows affected (0.00 sec) mysql>
-
验证授权是否成功
mysql> show grants for slave; +-------------------------------------------------------------------+ | Grants for slave@% | +-------------------------------------------------------------------+ | GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO `slave`@`%` | +-------------------------------------------------------------------+ 1 row in set (0.01 sec) mysql>
-
退出MySQL,使用新创建的用户slave来测试是否能连接,能正常进入就行。
sir-2:~ x$ mysql -h127.0.0.1 -P3307 -uslave -p123456 ... mysql>
3.0、配置从节点
-
进入容器交互环境,并安装vim以编辑/etc/mysql/my.cnf。
sir-2:~ x$ docker exec -it slave_mysql bash root@71c3bb3bcdbf:/# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime root@71c3bb3bcdbf:/# echo 'Asia/Shanghai' >/etc/timezone root@71c3bb3bcdbf:/# apt-get update ... root@71c3bb3bcdbf:/# apt-get install vim -y ... root@71c3bb3bcdbf:/# vim /etc/mysql/my.cnf
-
my.cnf
在[mysqld]
分区下添加下面内容后保存,exit退出容器交互环境。# 同一局域网内唯一ID server-id=2 # 开启二进制日志功能,以备Slave作为其它Slave的Master时使用 log-bin=mysql-slave-bin # relay_log配置中继日志,从主节点读取的二进制日志文件,写入relay_log中 relay_log=mysql-relay-bin # 配置日志文件 # 设置需要复制的库 # replicate-do-db=zdx # 设置需要复制的表 # replicate-do-table=tb1 # 使用通配符设置需要复制的表 # replicate-wild-do-table=test* log-slave-updates # 跳过从库错误 slave-skip-errors=all slave-net-timeout=60
-
重启slave容器
sir-2:~ x$ docker restart slave_mysql slave_mysql sir-2:~ x$
-
查看server-id是否已经修改
sir-2:~ x$ mysql -h127.0.0.1 -uroot -p123456 -P3308 ... mysql> show variables like 'server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 2 | +---------------+-------+ 1 row in set (0.01 sec) mysql>
-
查询主节点的容器的独立IP
sir-2:~ x$ docker inspect --format='{{.NetworkSettings.IPAddress}}' master_mysql 172.17.0.2 sir-2:~ x$
-
进入从节点MySQL,进行连接到主节点的配置,MASTER_HOST的IP为主节点的独立IP,MASTER_LOG_FILE和MASTER_LOG_POS对应主节点二进制日志文件的对应的值,重启从节点后需要重新执行6-7步骤。
mysql> CHANGE MASTER TO MASTER_HOST='172.17.0.2', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=156, MASTER_CONNECT_RETRY=30, MASTER_BIND=''; Query OK, 0 rows affected (0.02 sec) mysql>
-
在从节点启动同步用户,启动从数据库的复制线程。
# 启动slave用户 mysql> start slave user='slave' password='123456'; Query OK, 0 rows affected, 1 warning (0.00 sec) # 查看slave状态,查看复制是否成功,返回的Slave_IO_Running和Slave_SQL_Running都是Yes,则成功。 # Slave_IO_Running:表明与主节点的通信状况,若为no,检查能否ping通主节点,检查主节点防火墙,数据库是否启动等。 # Slave_SQL_Running:若为no,表明执行sql时出错。 mysql> show slave status\G;
4.0、测试数据同步
-
主节点创建数据库。
mysql> create database zdx default character set utf8; Query OK, 1 row affected, 1 warning (0.01 sec) mysql> create table zdx.tb1 (user varchar(30) not null, age int(10) not null) default charset utf8; Query OK, 0 rows affected, 2 warnings (0.02 sec) mysql> insert into zdx.tb1 value ('zhangsan', 18); Query OK, 1 row affected (0.00 sec) mysql>
-
从数据库是否同步数据,结果显示已经同步数据
mysql> select * from zdx.tb1; +----------+-----+ | user | age | +----------+-----+ | zhangsan | 18 | +----------+-----+ 1 row in set (0.01 sec) mysql>
5.0、遇到的问题
问题:在从库上show slave status\G时,发现slave_io_running: connecting
导致无法同步,日志显示:Last_IO_Error: error connecting to master 'slave@172.17.0.2:3306' - retry-time: 30 retries: 1 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
解决:MySQL版本8之后启用了新的默认认证插件,解决办法参考下面的前两篇文章。先使用docker exec -it slave_mysql bash
进入从库交互环境,需要现在从库上连接主库获取public-key。
sir-2:~ x$ docker exec -it slave_mysql bash
# slave是在主库上面创建的用于复制的账户
root@ccddf8133651:/# mysql --ssl-mode=DISABLED -h172.17.0.2 -uslave -p123456 --get-server-public-key
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 48
Server version: 8.0.22 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> exit;
Bye
root@ccddf8133651:/#
参考文章: