最近想自己开发一个小系统,而我的电脑里还没有安装任何的开发相关的配套软件和环境,所以想着方便以后开发的原则,就想从头到尾搭建一个mysql主从复制的数据库环境。一开始觉得这个搭建应该不难,网上有很多现成的资料而且有AI大模型的加持,所以理论上很快能搞定,可结果是我花了大概一天半的时间才算基本完成环境搭建,因此记录一下整个过程很有必要。
一、涉及软件及环境
|----|------------------|-----------------|
| 序号 | 软件名称 | 版本号 |
| 1 | Windows 11 家庭中文版 | 26100.4652 |
| 2 | Docker Desktop | 4.44.2 (202017) |
| 3 | MySql | 9.4.0 |
| 4 | DBeaver | 25.1.0 |
二、Docker Desktop下载&安装
Docker Desktop下载地址:https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe?utm_source=docker&utm_medium=webreferral&utm_campaign=dd-smartbutton&utm_location=module
下载之后直接双击"Docker Desktop Installer.exe"安装即可
安装Docker Desktop后,需要配置一下国内镜像,否则无法下载Docker镜像文件;
1、以管理员身份运行Docker Desktop之后,点击上面的配置图标,如下:
2、然后点击左侧"Docker Engine"菜单,在右侧配置国内镜像,如下:
温馨提示:国内镜像可能随时会无法正常提供服务,还请及时更新这个源。
3、配置完成之后,点击右上角"X"关闭,然后来到主窗口,点击左侧"Images",如下:
然后点击右下角的终端窗口,如下:
将会出现终端窗口,如下:
至此,我们的准备工作基本上完成了,现在就可以愉快的在光标出执行docker的各种操作了。
三、MySql 9.4.0下载&安装
1、在终端里输入命令"docker pull mysql:latest",下载mysql
温馨提示:如果想跟我一样的话,请将latest替换成"9.4.0"
2、mysql安装准备工作
- 新建docker的挂载目录,我是在D:\Users\Docker
- 在Docker文件夹下新建挂载目录下按照如下说明创建目录,如下:
其中WSL是Docker Desktop设置window Linux 子系统的位置,如下:
3、mysql安装 - 配置主数据库my.cnf
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=101
## 指定不需要同步的数据库名称
binlog-ignore-db=sys
## 开启二进制日志功能
log-bin=mysql-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=row
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
binlog_expire_logs_seconds = 604800 ##7天对应的秒数
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
##设置ssl证书
require_secure_transport=ON
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
- 配置从数据库my.cnf
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=sys
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=row
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
binlog_expire_logs_seconds = 604800 ##7天对应的秒数
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay-log=mysql-relay-bin # 固定日志文件名前缀
relay-log-index=mysql-relay-bin.index
##relay-log-info-repository=TABLE # 8.0+推荐使用表存储
relay-log-recovery=ON # 崩溃后自动恢复
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
slave_net_timeout=60 # 网络超时时间(秒)
master_retry_count=86400 # 最大重试次数(24小时*3600秒)
##master_connect_retry=10 # 重试间隔(秒)
replica_parallel_workers=4 # 并行复制线程数
##设置ssl证书
require_secure_transport=ON
ssl-ca=/etc/mysql/ssl/ca-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
- 新建一个共享的网络
docker network create mysql-replication
这个主要是为了主从复制的时候处于同一个网络中,便于网络访问
4. 启动mysql 主库的 docker命令
docker run -p 3306:3306 --name mysql_master --network mysql-replication -v D:\\Users\\Docker\\Volumes\\mysql-master\\log:/var/log/mysql -v D:\\Users\\Docker\\Volumes\\mysql-master\\data:/var/lib/mysql -v D:\\Users\\Docker\\Volumes\\mysql-master\\conf\\my.cnf:/etc/my.cnf -v D:\\Users\\Docker\\Volumes\\shared\\ssl:/etc/mysql/ssl -e MYSQL_ROOT_PASSWORD=sasa989 -e MYSQL_ALLOW_PUBLIC_KEY_RETRIEVAL=true -d mysql:latest
- 在主库容器实例的终端重新生成有效证书(需进入MySQL容器)
- 首先,切换到mysql的SSL证书目录来存储证书和密钥文件。
cd /etc/mysql/ssl
- 然后,生成自签名的CA证书和私钥。
openssl genrsa -out ca-key.pem 4096 openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca-cert.pem
在此处,4096位的ca-key.pem使用OpenSSL生成了一个RSA私钥,并使用该密钥签署了一个自签名X.509证书,并保存为ca-cert.pem。在输入提供关于组织和公钥的一些基本信息后,将生成ca-cert.pem文件。
- 接下来,生成服务器证书和私钥。
openssl req -newkey rsa:4096 -days 3650 -nodes -keyout server-key.pem -out server-req.pem openssl x509 -req -in server-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem -subj "/CN=mysql-master"
这里OpenSSL生成一个4096位的RSA私钥,并使用该密钥创建服务器证书签名请求server-req.pem。然后,服务器证书从签名请求生成,使用先前创建的CA证书ca-cert.pem和私钥ca-key.pem进行签名,使用序列号01,并保存为server-cert.pem。
最后,如果不是按照本文提供的mysql配置挂载目录的方式还需要将证书和密钥文件复制到MySQL从服务器和客户端所在的目录上。
- 最后确保mysql有读取证书的权限,参见第10操作
- 启动mysql 从库的 docker命令
docker run -p 3307:3306 --name mysql_slave --network mysql-replication -v D:\\Users\\Docker\\Volumes\\mysql-slave\\log:/var/log/mysql -v D:\\Users\\Docker\\Volumes\\mysql-slave\\data:/var/lib/mysql -v D:\\Users\\Docker\\Volumes\\mysql-slave\\conf\\my.cnf:/etc/my.cnf -v D:\\Users\\Docker\\Volumes\\shared\\ssl:/etc/mysql/ssl -e MYSQL_ROOT_PASSWORD=sasa989 -e MYSQL_ALLOW_PUBLIC_KEY_RETRIEVAL=true -d mysql:latest
- 在主库容器实例内创建数据同步用户
- 在主库创建同步账户 Slave:
CREATE USER 'slave'@'%' IDENTIFIED BY 'abc@123';--密码自己设置
- 添加账户权限:
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%'; FLUSH PRIVILEGES;
- 在主库容器实例内主数据库中查看主从同步状态
SHOW BINARY LOG STATUS;
- 在从库容器实例内从数据库中配置主从复制
- 进入容器终端,在Docker Desktop主窗口里,点击左侧的"Containers",然后出现正在运行的容器实例,如下:
- 然后点击上图的箭头位置,在弹出的菜单里点击"Open in terminal"即可进入容器实例终端,如下
- 在容器终端里输入mysql的命令进入mysql命令执行终端,如下:
mysql -uroot -p
- 在终端里配置主从复制
STOP REPLICA; -- 停止现有复制
CHANGE REPLICATION SOURCE TO SOURCE_HOST='mysql_master', # 使用主库容器名
SOURCE_SSL=1,
SOURCE_SSL_CA='/etc/mysql/ssl/ca-cert.pem',
SOURCE_SSL_CERT='/etc/mysql/ssl/server-cert.pem',
SOURCE_SSL_KEY='/etc/mysql/ssl/server-key.pem',
SOURCE_LOG_FILE='mysql-bin.000006', # 主库SHOW BINARY LOG STATUS结果
SOURCE_LOG_POS=688;
START REPLICA USER='slave' PASSWORD='abc@123';
- 确保私钥文件权限正确
- 在主库和从库的终端执行如下命令,确保mysql有权限读取server-key.pem
chmod 600 /etc/mysql/ssl/server-key.pem chown mysql:mysql /etc/mysql/ssl/server-key.pem
- 测试主从复制
- 在DBeaver里,新建数据库连接
- 在DBeaver里,点击"驱动属性",将红色的属性设置为"TRUE"
- 在DBeaver里,点击"SSL",勾选使用SSL,并设置红框里的高级参数
- 点击确定之后就可以连接数据库。
- 在主数据库里新建数据库"product"(等一会再创建表,要不从数据库无法及时同步数据库创建会出现其它的错误)
CREATE DATABASE `product` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
类似的错误如下:
ERROR\] \[MY-010584\] \[Repl\] Replica SQL for channel '': Worker 1 failed executing transaction 'ANONYMOUS' at source log mysql-bin.000005, end_log_pos 1867; Error 'Unknown database 'test'' on query. Default database: ''. Query: '/\* ApplicationName=DBeaver 25.1.0 - Main \*/ CREATE TABLE test.t ( id int PRIMARY key, name varchar(20) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci', Error_code: MY-001049 2025-08-21T02:55:01.228876Z 17 \[Warning\] \[MY-010584\] \[Repl\] Replica SQL for channel '': ... The replica coordinator and worker threads are stopped, possibly leaving data in inconsistent state. A restart should restore consistency automatically, although using non-transactional storage for data or info tables or DDL queries could lead to problems. In such cases you have to examine your data (see documentation for details). Error_code: MY-001756
CREATE TABLE `order` ( `id` int NOT NULL AUTO_INCREMENT, `product_id` int DEFAULT '0', `order_no` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
- 连接从数据库,如果从数据库已经同步了主数据库product里的表order,则在表order新建数据
在主数据库新增一条记录,
在从数据库里查看同步记录
至此,整个mysql 9的主从复制就算搭建完成了。
四、总结
1、MySql 9主从复制的时候出现认证插件需要安全连接错误
这个错误信息表明,在尝试连接到MySQL服务器时,由于认证插件caching_sha2_password要求使用安全连接,而当前的连接没有满足这一要求,因此认证失败。
caching_sha2_password是MySQL 8.0.4及以上版本引入的一个新的身份验证插件,它对密码安全性要求更高,要求在网络传输过程中密码是加密的。
类似的错误信息如下:
Error connecting to source 'slave@mysql_master:3306'. This was attempt 2/10, with a delay of 60 seconds between attempts. Message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection. Error_code: MY-002061
解决方法:按照文中的要求进入容器终端生成证书
2、SSL证书生成的误区
我一开始SSL证书生成,误以为在我window11机器上生成,然后直接放到挂载的目录里D:\Users\Docker\Volumes\shared\ss即可,这个错误导致一直报错,类似错误如下:
Repl\] Replica I/O for channel '': Error connecting to source 'slave@mysql_master:3306'. This was attempt 10/10, with a delay of 60 seconds between attempts. Message: SSL connection error: Unable to get private key, Error_code: MY-002026 **解决方法:按照文中的要求进入容器终端生成证书并且给证书读取权限** **3、确保主库Host配置正确** 我一开始配置Host为mysql-master,这个只是我挂载目录的名称,我们需要配置的是容器运行时的name属性或者是DNSNames里的字符串,在Docker里可以查看容器的Inspect看到,如下: 否则会出现如下类似的错误: Error connecting to source 'slave@mysql-master:3306'. This was attempt 7/10, with a delay of 60 seconds between attempts. Message: Unknown MySQL server host 'mysql-master' (-2) **4、主从复制配置的时候,不要配置账号密码,确保安全** 我一开始将同步的账号密码配置在同步语句里,如下: ``` -- 在从库容器内执行 STOP REPLICA; -- 停止现有复制 CHANGE REPLICATION SOURCE TO SOURCE_HOST='"mysql_master', # 使用主库容器名mysql_master SOURCE_USER='slave', SOURCE_PASSWORD='abc@123', SOURCE_SSL=1, SOURCE_SSL_CA='/etc/mysql/ssl/ca-cert.pem', SOURCE_SSL_CERT='/etc/mysql/ssl/server-cert.pem', SOURCE_SSL_KEY='/etc/mysql/ssl/server-key.pem', SOURCE_LOG_FILE='binlog.000010', # 主库SHOW BINARY LOG STATUS结果 SOURCE_LOG_POS=462; START REPLICA USER='slave' PASSWORD='abc@123'; ``` 然后看到mysql从数据库执行时输出如下错误: Storing MySQL user name or password information in the connection metadata repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START REPLICA; see the 'START REPLICA Syntax' in the MySQL Manual for more information. 后来改成如下语句: ``` STOP REPLICA; -- 停止现有复制 CHANGE REPLICATION SOURCE TO SOURCE_HOST='mysql_master', # 使用主库容器名 SOURCE_SSL=1, SOURCE_SSL_CA='/etc/mysql/ssl/ca-cert.pem', SOURCE_SSL_CERT='/etc/mysql/ssl/server-cert.pem', SOURCE_SSL_KEY='/etc/mysql/ssl/server-key.pem', SOURCE_LOG_FILE='mysql-bin.000006', # 主库SHOW BINARY LOG STATUS结果 SOURCE_LOG_POS=688; START REPLICA USER='slave' PASSWORD='abc@123'; ``` 5、当从库同步时输出元数据结构相关的问题,重置复制配置以及重新配置即可 当出现如下类似错误的时候: Replica failed to initialize applier metadata structure from the repository > 2025-08-21T02:24:12.162382Z 22 \[System\] \[MY-014001\] \[Repl\] Replica receiver thread for channel '': connected to source 'slave@mysql_master:3306' with server_uuid=d55239e3-7db5-11f0-8543-2e1613da1bf7, server_id=101. Starting replication from file 'binlog.000010', position '462'. 2025-08-21T02:24:12.163621Z 22 \[ERROR\] \[MY-010557\] \[Repl\] Error reading packet from server for channel '': Could not find first log file name in binary log index file (server_errno=1236) 2025-08-21T02:24:12.163662Z 22 \[ERROR\] \[MY-013114\] \[Repl\] Replica I/O for channel '': Got fatal error 1236 from source when reading data from binary log: 'Could not find first log file name in binary log index file', Error_code: MY-013114 重置从库复制元数据: ``` STOP REPLICA; RESET REPLICA ALL; -- MySQL 8.0+专用语法 ``` 需要去主库容器实例终端,在mysql命令里执行: ``` SHOW BINARY LOG STATUS; ``` 然后去从库容器实例终端,在mysql命令里执行: ``` STOP REPLICA; -- 停止现有复制 CHANGE REPLICATION SOURCE TO SOURCE_HOST='mysql_master', # 使用主库容器名 SOURCE_SSL=1, SOURCE_SSL_CA='/etc/mysql/ssl/ca-cert.pem', SOURCE_SSL_CERT='/etc/mysql/ssl/server-cert.pem', SOURCE_SSL_KEY='/etc/mysql/ssl/server-key.pem', SOURCE_LOG_FILE='mysql-bin.00000x', # 主库SHOW BINARY LOG STATUS新的结果 SOURCE_LOG_POS=xxx;# 主库SHOW BINARY LOG STATUS新的结果 START REPLICA USER='slave' PASSWORD='abc@123'; ``` 综上,本文是原创文章,转载请注明出处,谢谢。