Centos7.9 Docker26容器化部署 MySql9.4 一主一从的同步复制部署。我使用了一个mysql9.4:teamdhl-mysql-master 作为主库,一个mysql9.4:teamdhl-mysql-slave 作为从库,主库负责写入,从库负责查询。组成一主一从的同步复制架构。
我的实践过程:
第一次连接,不使用SSL,但MySQL 8.0+ 默认使用 caching_sha2_password
认证插件,该插件要求加密连接(SSL),失败
第一次连接,尝试将 repl
用户的认证插件改为不强制 SSL 的 mysql_native_password
,失败 ,错误原因是 MySQL 9.4 版本默认未加载 mysql_native_password
插件,该插件在高版本 MySQL 中已被弱化(默认仅支持 caching_sha2_password
)
第三次连接,尝试使用SSL连接,自动生成SSL证书,失败 ,在 MySQL 9.4 容器中,mysql_ssl_rsa_setup
命令已被移除,生成 SSL 证书的方式有所变化
第四次连接,尝试手动生成SSL证书并连接,成功
最终解决方案:手动配置SSL证书
步骤 1:为主库和从库准备自定义配置文件
主库 容器的配置文件夹conf/my.cnf (conf文件夹是本地文件夹,挂载的是容器的/etc/mysql/conf.d)
ini
[mysqld]
# 开启二进制日志(从库依赖它复制数据)
log-bin=mysql-bin
# 主库唯一标识(1-2^32,从库需不同)
server-id=1
# 要同步的数据库(可指定多个,*表示所有,这里同步 ry-vue 库)
binlog-do-db=ry-vue
# 不需要同步的数据库(可选,如系统库 mysql 可忽略)
binlog-ignore-db=mysql
# SSL 配置
ssl-ca=/var/lib/mysql/ssl/ca.pem
ssl-cert=/var/lib/mysql/ssl/server-cert.pem
ssl-key=/var/lib/mysql/ssl/server-key.pem
从库 容器的配置文件夹conf/my.cnf(conf文件夹是本地文件夹,挂载的是容器的/etc/mysql/conf.d)
ini
[mysqld]
# 从库唯一标识(必须与主库不同)
server-id=2
# 开启中继日志(从库复制主库 binlog 时的临时日志)
relay-log=relay-log
# 从库只读(普通用户无法写)
read_only=1
# 禁止 root 用户在从库写
super_read_only=1
**注意:在主从数据库都要有相同的数据库(在准备的时候),主库配置文件 my.cnf 中 binlog-do-db=ry-vue 可知道,主从库中都要有名为 ry-vue 的数据库才可以同步复制,不然在从库内部会执行 SHOW REPLICA STATUS\G; 时会报错 Last_Errno: 1049
(未知数据库)。**具体如何解决放在文章最后面。
预防措施
为避免此类问题,建议:
-
在主库创建数据库后,先手动在从库创建同名数据库,再执行表结构或数据操作。
-
若希望主库自动同步数据库创建操作,可在主库配置中
删除
binlog-do-db
限制(即不指定同步特定库,默认同步所有库):
ini
ini# 编辑主库 my.cnf,注释或删除以下行 # binlog-do-db=ry-vue
重启主库后,主库的
CREATE DATABASE
相关操作会自动同步到从库。
步骤 2:在主库容器中手动生成 SSL 证书
bash
bash
# 进入主库容器
docker exec -it teamdhl-mysql-master bash
# 创建证书目录
mkdir -p /var/lib/mysql/ssl
cd /var/lib/mysql/ssl
# 使用 openssl 生成 SSL 证书(依次执行以下命令)
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca.pem
openssl genrsa 2048 > server-key.pem
openssl req -new -key server-key.pem -out server-req.pem
openssl x509 -req -in server-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
openssl genrsa 2048 > client-key.pem
openssl req -new -key client-key.pem -out client-req.pem
openssl x509 -req -in client-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 02 > client-cert.pem
# 授权 MySQL 用户访问证书
chown -R mysql:mysql /var/lib/mysql/ssl
注意:
在执行 openssl req
命令时,需要填写证书的相关信息(如国家、组织等),这些信息是证书的元数据,可简单填写或直接留空(按回车跳过)。
针对你遇到的 "Country Name" 输入问题:
-
国家代码 需要填写2 个字母 (如中国填
CN
,美国填US
),例如:plaintext
plaintextCountry Name (2 letter code) [XX]:CN
-
后续其他字段可直接按回车留空(或简单填写):
plaintext
plaintextState or Province Name (full name) []: Locality Name (eg, city) []: Organization Name (eg, company) []: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []: Email Address []:
步骤 3:在主库中配置 SSL 并授权用户
进入主库 MySQL 终端:
bash
bash
mysql -uroot -p
执行执行授权 SQL(%
表示允许从任意 IP 连接,生产环境建议限制 IP):
sql
sql
-- 启用 SSL
SET GLOBAL ssl=ON;
-- 授权 repl 用户使用 SSL 连接
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' REQUIRE SSL;
FLUSH PRIVILEGES;
查看主库当前的 binlog 位置(记录 File
和 Position
,从库需要用):
sql
sql
# 必须在主库中执行,从库不支持该命令
# SHOW MASTER STATUS; # mysql9.4不支持
SHOW BINARY LOG STATUS;
输出类似:
plaintext
plaintext
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | ruoyi_wms | | |
+------------------+----------+--------------+------------------+-------------------+
记录 File
(如 mysql-bin.000001
)和 Position
(如 154
)
注意:重启容器后 position 会发生变化
步骤 4:将主库 SSL 证书复制到从库
在宿主机执行(将主库生成的证书复制到从库容器):
bash
bash
# 从主库容器复制证书到宿主机临时目录
docker cp teamdhl-mysql-master:/var/lib/mysql/ssl /tmp/
# 将证书复制到从库容器
docker cp /tmp/ssl teamdhl-mysql-slave:/var/lib/mysql/
# 为从库证书授权
docker exec -it teamdhl-mysql-slave chown -R mysql:mysql /var/lib/mysql/ssl
步骤 5:在从库中配置 SSL 同步
进入从库 MySQL 终端:
bash
bash
docker exec -it teamdhl-mysql-slave mysql -uroot -p
验证从库证书是否存在
bash
bash
# 查看从库容器内的证书文件
docker exec -it teamdhl-mysql-slave ls -l /var/lib/mysql/ssl
如果看到类似以下输出,说明证书已正确复制:
plaintext
plaintext
-rw------- 1 mysql mysql 1675 Aug 22 10:00 ca-key.pem
-rw------- 1 mysql mysql 1359 Aug 22 10:00 ca.pem
-rw------- 1 mysql mysql 1679 Aug 22 10:01 client-key.pem
-rw------- 1 mysql mysql 1359 Aug 22 10:01 client-cert.pem
-rw------- 1 mysql mysql 1675 Aug 22 10:00 server-key.pem
-rw------- 1 mysql mysql 1359 Aug 22 10:00 server-cert.pem
配置同步:
sql
sql
STOP REPLICA;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='teamdhl-mysql-master',
SOURCE_USER='repl',
SOURCE_PASSWORD='HIH.20171009',
SOURCE_PORT=3306,
SOURCE_LOG_FILE='mysql-bin.000001',
SOURCE_LOG_POS=158,
SOURCE_SSL=1 # 仅启用SSL,不指定证书路径,防止路径报错问题
START REPLICA;
步骤 6:验证同步状态
sql
sql
SHOW REPLICA STATUS\G;
若 Replica_IO_Running
和 Replica_SQL_Running
均为 Yes
,则主从同步通过 SSL 连接成功建立。
这种方式通过 openssl
手动生成证书,兼容 MySQL 9.4 版本,解决了 mysql_ssl_rsa_setup
命令不存在的问题。
步骤 7:验证同步功能(可选)
-
在主库创建测试数据:
sql
sql-- 进入主库 docker exec -it teamdhl-mysql-master mysql -uroot -p -- 创建测试数据库(如果不存在) CREATE DATABASE IF NOT EXISTS test_sync; USE test_sync; -- 创建测试表并插入数据 CREATE TABLE IF NOT EXISTS test_table (id INT, name VARCHAR(20)); INSERT INTO test_table VALUES (1, 'sync_test');
-
在从库查看是否同步成功:
sql
sql-- 进入从库 docker exec -it teamdhl-mysql-slave mysql -uroot -p -- 查看同步的数据 USE test_sync; SELECT * FROM test_table;
如果能看到主库插入的数据,说明同步功能正常工作。
恭喜你完成了 MySQL 9.4 的主从同步配置!
从库 Last_Errno: 1049
(未知数据库)解决方案
在从库中执行SHOW REPLICA STATUS\G;
从输出的状态信息来看,从库的 SQL 线程(Replica_SQL_Running: No
)已中断 ,错误原因是 Last_Errno: 1049
(未知数据库),具体是主库执行的事务涉及从库不存在的数据库,导致从库无法执行中继日志中的 SQL。
具体原因
主库中创建了某个数据库(如 test_sync
或 navicat_test
所在的库),但从库中不存在该数据库 ,当主库的 binlog 同步到从库时,从库执行 CREATE TABLE
或 INSERT
操作时会因 "找不到数据库" 而报错,导致 SQL 线程停止。
解决方案:手动创建缺失的数据库并重启同步
步骤 1:确定主库中操作的数据库名称
查看主库中你测试时使用的数据库(例如 test_sync
所在的库)。
步骤 2:在从库中创建相同的数据库
在从库 MySQL 终端执行:
sql
sql
-- 替换为实际缺失的数据库名(例如 test_sync)
CREATE DATABASE IF NOT EXISTS test_sync;
步骤 3:跳过错误并重启同步
sql
sql
-- 跳过当前错误事务(仅用于解决此问题,不要频繁使用)
SET GLOBAL sql_slave_skip_counter = 1;
-- 重启从库同步
STOP REPLICA;
START REPLICA;
步骤 4:验证同步状态
sql
sql
SHOW REPLICA STATUS\G;
确认 Replica_SQL_Running
变为 Yes
,且 Last_SQL_Error
为空。
步骤 5:重新测试同步
-
在主库创建测试数据:
sql
sql-- 进入主库 docker exec -it teamdhl-mysql-master mysql -uroot -p -- 创建测试数据库(如果不存在) CREATE DATABASE IF NOT EXISTS test_sync; USE test_sync; -- 创建测试表并插入数据 CREATE TABLE IF NOT EXISTS test_table (id INT, name VARCHAR(20)); INSERT INTO test_table VALUES (1, 'sync_test');
-
在从库查看是否同步成功:
sql
sql-- 进入从库 docker exec -it teamdhl-mysql-slave mysql -uroot -p -- 查看同步的数据 USE test_sync; SELECT * FROM test_table;
如果能看到主库插入的数据,说明同步功能正常工作。
通过以上步骤,可解决 "未知数据库" 导致的同步中断问题,恢复主从数据同步。