乘风破浪,遇见云原生(Cloud Native)之Docker Desktop for Windows 运行MYSQL多实例并实现主从(Master-Slave)部署

什么是MYSQL主从模式

image

主从复制过程使数据库管理员能够同时复制或拷贝存储在多个服务器中的数据。这有助于数据库管理员一直创建数据库的实时备份。在某些情况下,当主从机出现任何问题时,他们可以立即切换到从机数据库,并保持应用程序正常运行。复制过程确保你的应用程序根本不会面临任何形式的停机。

在这种复制中,有各种类型的复制过程。你可以有一个主站和多个从站,或者多个主站和多个从站等。

在这个过程中,它总是一个单一的或单向的数据传输。数据首先存储在主站,然后再复制到从站。因此,写操作只在主数据库中进行。读取操作是在主数据库和从数据库中进行的。从机也可用于数据访问,以减少主数据库的负荷

部署主从实例

新建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

image

新建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

image

新建名为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

image

为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

image

等下的主从同步都是基于这些信息来同步的,如果不一致的话,会出现错误。

配置Master实例

先将Master实例中配置文件拷贝出来

docker cp mysql-master:/etc/my.cnf F:\mysql-master\my.cnf

image

通过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

image

将修改后的配置文件拷贝回Master实例

docker cp F:\mysql-master\my.cnf mysql-master:/etc/my.cnf

然后重启一次Master实例

docker restart mysql-master

image

进入Master实例

docker exec -it mysql-master /bin/bash

image

登录mysql

mysql -u root -p

然后输入密码

image

登录成功后,通过命令查看log-bin是否开启成功

show variables like '%log_bin%';

image

创建用于主从复制的账号

create user 'repl-from-master'@'%' identified by 'xxxxxxxxxx';

image

并且授予其复制权限

grant replication slave,replication client on *.* to 'repl-from-master'@'%';

image

查看实例状态

show master status;

image

这里的FilePosition都是我们Slave需要用到的信息,记录下来。

另外,quit之后,还可以切换到log-bin数据目录也应该可以看到日志文件

cd /var/lib/mysql/
ls

image

配置Slave实例

先将Slave实例中配置文件拷贝出来

docker cp mysql-slave-01:/etc/my.cnf F:\mysql-slave-01\my.cnf

image

通过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

image

将修改后的配置文件拷贝回Slave实例

docker cp F:\mysql-slave-01\my.cnf mysql-slave-01:/etc/my.cnf

然后重启一次Slave实例

docker restart mysql-slave-01

image

进入Slave实例

docker exec -it mysql-slave-01 /bin/bash

image

登录mysql

mysql -u root -p

然后输入密码

image

登录成功后,为了防止之前有设置过Slave,我们先做一次停止

stop slave;

image

通过命令设置它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;

image

这些参数的含义分别是

  • master_host=主数据库IP
  • master_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可以查阅。

image

重置一次同步

reset slave;

image

然后开始执行同步

start slave;

image

查看同步状态

show slave status \G;

这里使用了\G代表以键值对的方式输出结果。

image

其中Slave_IO_RunningSlave_SQL_Running都为Yes,才算是正常。

处理异常情况

如果这时候Slave_IO_RunningNo,我们可以考虑先停止Slave

stop slave;

再回到Master里面,在mysql模式下,执行

flush logs;

刷新下日志。

再次查看位置

show master status;

image

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;

image

验证主从同步

我们先在Master的tesla库的order表中新增一条数据。

image

接下来,我们去Slave的tesla库的order表中看看

image

如果它在那里,并且和Master保持一致,那么就同步成功了。

常见错误

Error_code: 2003

这个错误表示,连接Master用的master_hostmaster_portmaster_usermaster_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

参考

posted @ 2022-10-29 21:51  TaylorShi  阅读(278)  评论(0编辑  收藏  举报