Centos7.9 Docker26容器化部署 MySql9.4 一主一从的同步复制部署

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(未知数据库)。**具体如何解决放在文章最后面。

预防措施

为避免此类问题,建议:

  1. 在主库创建数据库后,先手动在从库创建同名数据库,再执行表结构或数据操作。

  2. 若希望主库自动同步数据库创建操作,可在主库配置中

    删除 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" 输入问题:

  1. 国家代码 需要填写2 个字母 (如中国填 CN,美国填 US),例如:

    plaintext

    plaintext 复制代码
    Country Name (2 letter code) [XX]:CN
  2. 后续其他字段可直接按回车留空(或简单填写):

    plaintext

    plaintext 复制代码
    State 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 位置(记录 FilePosition,从库需要用):

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_RunningReplica_SQL_Running 均为 Yes,则主从同步通过 SSL 连接成功建立。

这种方式通过 openssl 手动生成证书,兼容 MySQL 9.4 版本,解决了 mysql_ssl_rsa_setup 命令不存在的问题。

步骤 7:验证同步功能(可选)
  1. 在主库创建测试数据:

    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');
  2. 在从库查看是否同步成功:

    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_syncnavicat_test 所在的库),但从库中不存在该数据库 ,当主库的 binlog 同步到从库时,从库执行 CREATE TABLEINSERT 操作时会因 "找不到数据库" 而报错,导致 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:重新测试同步
  1. 在主库创建测试数据:

    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');
  2. 在从库查看是否同步成功:

    sql

    sql 复制代码
    -- 进入从库
    docker exec -it teamdhl-mysql-slave mysql -uroot -p
    
    -- 查看同步的数据
    USE test_sync;
    SELECT * FROM test_table;

如果能看到主库插入的数据,说明同步功能正常工作。

通过以上步骤,可解决 "未知数据库" 导致的同步中断问题,恢复主从数据同步。

相关推荐
.Shu.1 小时前
Mysql InnoDB 底层架构设计、功能、原理、源码系列合集【五、InnoDB 高阶机制与实战调优】
数据库·mysql
新法国菜3 小时前
MySql知识梳理之DDL语句
数据库·mysql
刘一说4 小时前
CentOS安装Maven详细教程
linux·centos·maven
叁沐6 小时前
MySQL 28 读写分离有哪些坑?
mysql
DarkAthena7 小时前
【GaussDB】使用MySQL客户端连接到GaussDB的M-Compatibility数据库
数据库·mysql·gaussdb
帧栈16 小时前
开发避坑指南(29):微信昵称特殊字符存储异常修复方案
java·mysql
瓜酷月..16 小时前
MySQL的高可用+MHA
数据库·mysql
苹果醋320 小时前
Java并发编程-Java内存模型(JMM)
java·运维·spring boot·mysql·nginx
翔云12345621 小时前
Python 中 SQLAlchemy 和 MySQLdb 的关系
数据库·python·mysql