乘风破浪,遇见云原生(Cloud Native)之Docker Desktop for Windows 运行MYSQL多实例并实现主从(Master-Slave)部署
什么是MYSQL主从模式
主从复制过程使数据库管理员能够同时复制或拷贝存储在多个服务器中的数据。这有助于数据库管理员一直创建数据库的实时备份。在某些情况下,当主从机出现任何问题时,他们可以立即切换到从机数据库,并保持应用程序正常运行。复制过程确保你的应用程序根本不会面临任何形式的停机。
在这种复制中,有各种类型的复制过程。你可以有一个主站和多个从站,或者多个主站和多个从站等。
在这个过程中,它总是一个单一的或单向的数据传输。数据首先存储在主站,然后再复制到从站。因此,写操作只在主数据库中进行。读取操作是在主数据库和从数据库中进行的。从机也可用于数据访问,以减少主数据库的负荷。
部署主从实例
新建Master实例
新建名为mysql-master
的实例,端口16000
docker run -d --name mysql-master --restart unless-stopped -p 16000:3306 -e MYSQL_ROOT_PASSWORD=xxxxxxxxxxxxx mysql:5.7.40
新建Slave实例
新建名为mysql-slave-01
的实例,端口17001
docker run -d --name mysql-slave-01 --restart unless-stopped -p 17001:3306 -e MYSQL_ROOT_PASSWORD=xxxxxxxxxxxxx mysql:5.7.40
新建名为mysql-slave-02
的实例,端口17002
docker run -d --name mysql-slave-02 --restart unless-stopped -p 17002:3306 -e MYSQL_ROOT_PASSWORD=xxxxxxxxxxxxx mysql:5.7.40
为Master和Slave创建库表
我们可以使用一些SQL工具连接到Master和所有的Slave,然后通过下面语句创建好数据库tesla
和它名下的数据表order
CREATE DATABASE IF NOT EXISTS tesla;
USE tesla;
CREATE TABLE IF NOT EXISTS `order` (
`id` int(11) NOT NULL,
`name` varchar(254) NOT NULL,
`bir` varchar(254) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
等下的主从同步都是基于这些信息来同步的,如果不一致的话,会出现错误。
配置Master实例
先将Master实例中配置文件拷贝出来
docker cp mysql-master:/etc/my.cnf F:\mysql-master\my.cnf
通过VSCode编辑它,在[client]
之前位置,插入两行配置
skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
# 开启Log_bin
log-bin=mysql.bin
# 指定全局唯一ID
server-id=11
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
#log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
其中log-bin=mysql.bin
指定了BinLog日志的相对位置,最终会记录在/var/lib/mysql/mysql.bin
,然后server-id=11
,给这个Master实例指定了唯一ID。
这里还有一些可选的配置:
# 无需同步的数据库名称
binlog-ignore-db=mysql
# 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
# 设置二进制日志过期清理时间,默认值为0,,表示不自动清理
expire_logs_days=7
# 跳过主从复制中遇到的所有错误或者指定类型的错误,避免slave端的复制中断
# 如1062错误是指一些主键重复,1032错误是指主从数据库的数据不一致。
slave_skip_errors=1062
将修改后的配置文件拷贝回Master实例
docker cp F:\mysql-master\my.cnf mysql-master:/etc/my.cnf
然后重启一次Master实例
docker restart mysql-master
进入Master实例
docker exec -it mysql-master /bin/bash
登录mysql
mysql -u root -p
然后输入密码
登录成功后,通过命令查看log-bin是否开启成功
show variables like '%log_bin%';
创建用于主从复制的账号
create user 'repl-from-master'@'%' identified by 'xxxxxxxxxx';
并且授予其复制权限
grant replication slave,replication client on *.* to 'repl-from-master'@'%';
查看实例状态
show master status;
这里的File
和Position
都是我们Slave需要用到的信息,记录下来。
另外,quit
之后,还可以切换到log-bin数据目录也应该可以看到日志文件
cd /var/lib/mysql/
ls
配置Slave实例
先将Slave实例中配置文件拷贝出来
docker cp mysql-slave-01:/etc/my.cnf F:\mysql-slave-01\my.cnf
通过VSCode编辑它,在[client]
之前位置,插入两行配置
skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
# 指定全局唯一ID
server-id=21
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
#log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
其中server-id=21
,给这个Slave实例指定了唯一ID。
这里还有一些可选的配置:
# 无需同步的数据库名称
binlog-ignore-db=mysql
# 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
# 设置二进制日志过期清理时间,默认值为0,,表示不自动清理
expire_logs_days=7
# 跳过主从复制中遇到的所有错误或者指定类型的错误,避免slave端的复制中断
# 如1062错误是指一些主键重复,1032错误是指主从数据库的数据不一致。
slave_skip_errors=1062
# 将复制事件写入自己的二进制日志
log_slave_updates=1
# 设置数据库数据为只读(具有super权限的用户除外)
read_only=1
将修改后的配置文件拷贝回Slave实例
docker cp F:\mysql-slave-01\my.cnf mysql-slave-01:/etc/my.cnf
然后重启一次Slave实例
docker restart mysql-slave-01
进入Slave实例
docker exec -it mysql-slave-01 /bin/bash
登录mysql
mysql -u root -p
然后输入密码
登录成功后,为了防止之前有设置过Slave,我们先做一次停止
stop slave;
通过命令设置它Slave哪个Master,相关连接信息和位置是多少。
change master to master_host='192.168.0.109',master_port=16000, master_user='repl-from-master',master_password='xxxxxxxxxxxx',master_log_file='mysql-bin.000004',master_log_pos=154;
这些参数的含义分别是
master_host
=主数据库IPmaster_port
=主数据端口master_user
=在主数据库创建的用于同步的用户账号master_password
=在主数据库创建的用于同步的用户密码master_log_file
=指定从主数据库复制数据的日志文件,查看主数据状态的File字段的值master_log_pos
=指定从主数据库哪个位置开始复制数据,查看主数据状态的Position字段的值master_connect_retry
=从数据库连接主数据库失败时,重新尝试连接的间隔时间,单位秒
这里有个要特别注意的地方,
master_host
不能使用localhost
或者127.0.0.1
这样的,如果是Docker Desktop for Windows可以使用本机的局域网Ip,通过ipconfig
可以查阅。
重置一次同步
reset slave;
然后开始执行同步
start slave;
查看同步状态
show slave status \G;
这里使用了\G
代表以键值对的方式输出结果。
其中Slave_IO_Running
和Slave_SQL_Running
都为Yes
,才算是正常。
处理异常情况
如果这时候Slave_IO_Running
为No
,我们可以考虑先停止Slave
stop slave;
再回到Master里面,在mysql
模式下,执行
flush logs;
刷新下日志。
再次查看位置
show master status;
File的名字会+1
回到Slave实例中更新位置
change master to master_log_file='mysql-bin.000002',master_log_pos=154;
然后先重置一次
reset slave;
然后启动并查看Slave状态
start slave;
show slave status \G;
验证主从同步
我们先在Master的tesla
库的order
表中新增一条数据。
接下来,我们去Slave的tesla
库的order
表中看看
如果它在那里,并且和Master保持一致,那么就同步成功了。
常见错误
Error_code: 2003
这个错误表示,连接Master用的master_host
、master_port
、master_user
、master_password
四个信息里面肯定错了至少一个。
[ERROR] Slave I/O for channel '': error connecting to master 'repl-from-master@localhost:16000' - retry-time: 60 retries: 1, Error_code: 2003
Error_code: 1236
这个错误表示,没有读取到Master BinLog正确的日志文件,如果确实文件都在,做一次Master的flush logs;
动作,在来Slave修正下位置试试。
[ERROR] Slave I/O for channel '': Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file', Error_code: 1236
Error_code: 1051
这个错误表示,同步过来一个删表动作,但是Slave中根本没有这个表,估计也是Slave没有同步创建好这张表。
[ERROR] Slave SQL for channel '': Error 'Unknown table 'tesla.order'' on query. Default database: 'tesla'. Query: 'DROP TABLE `order` /* generated by server */', Error_code: 1051
Error_code: 1146
这个错误表示,在Slave中都没有找到这个名称的表,可能是Master里面新建了,但是在Slave中没有对应的建,这里补创建下就好了。
[ERROR] Slave SQL for channel '': Error executing row event: 'Table 'tesla.order' doesn't exist', Error_code: 1146
Error_code: 1032
这个错误表示,同步过来一个删除动作,但是Slave中没有这条记录。
[ERROR] Slave SQL for channel '': Could not execute Delete_rows event on table tesla.order; Can't find record in 'order', Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event's master log mysql.000007, end_log_pos 1662, Error_code: 1032
参考
- Docker cp命令
- docker精简版没有vi,vim命令,怎么修改文件
- 【docker+mysql】基于docker 配置 mysql5.7 主从 master-slave
- mysql数据库开启log-bin
- 'COULD NOT FIND FIRST LOG FILE NAME IN BINARY LOG INDEX FILE'的解决办法
- canal异常 Could not find first log file name in binary log index file
- Docker部署MySQL 8.0主从(Master-Slave)
- MySQL 创建数据表
- Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file n
- Error 1236 - "Could not find first log file name in binary log index file"