暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

记一次MySQL 5.7->8.4 升级踩坑记:跨版本复制中 SSL 证书与认证插件

一、背景与问题

在一次标准的数据库升级工作中,我们遇到了一个极具挑战性的场景:搭建 MySQL 5.7 主库 → MySQL 8.4 从库的复制环境。看似常规的操作,却引发了一连串「灵异」的客户端连接失败与 SSL 报错。本文完整复盘从问题现象、错误分析到最终解决方案的全过程,并附上详尽的操作日志,为计划进行类似升级的同行提供避坑指南。

角色 主机 MySQL 版本 IP 特殊要求
主库 db-master-01 5.7 10.0.1.10 必须启用 SSL
从库 db-slave-01 8.4 10.0.1.20 必须启用 SSL

核心要求:客户端与复制链路均需强制 SSL 加密连接。


二、探案之旅:层出不穷的错误现象

我们的排查之旅充满了迷惑性的错误,每解决一个,似乎都会触发一个新的、更深层次的问题。

2.1 第一站:Access denied——经典的「密码错误」假象

ERROR 1045 (28000): Access denied for user 'app_user'@'10.0.2.100'

排查过程

mysql> SHOW CREATE USER 'app_user'@'10.0.2.100'\G CREATE USER `app_user`@`10.0.2.100` ... REQUIRE X509 ...
  • app_user 被创建时强制 REQUIRE X509
  • 客户端连接时未带证书,仅凭密码 → 被从库直接拒绝

2.2 第二站:certificate verify failed——证书的「身份危机」

SSL connection error: certificate verify failed

排查过程

[root@db-slave-01 ~]# openssl x509 -in /db01/mysql/server-cert.pem -noout -subject Subject: CN=MySQL_Server_8.4.6_Auto_Generated_Server_Certificate
  • 从库使用初始化自动生成的自签证书
  • 证书 Subject/SAN 不包含主机名或 IP
  • 客户端在 VERIFY_IDENTITY 模式下严格比对失败

2.3 第三站:Invalid certificates——「灵异」的加载失败

mysql> ALTER INSTANCE RELOAD TLS; ERROR 3888 (HY000): Invalid certificates

外部验证正常:

[root@db-slave-01 ~]# openssl verify -CAfile /db01/mysql/ssl/ca.pem /db01/mysql/ssl/server-cert.pem /db01/mysql/ssl/server-cert.pem: OK

原因:证书文件中存在不可见字符(BOM / CRLF)或 SELinux 上下文、权限不当。
解决:对证书文件做「净化」→ 重新 cat > new.pem 并严格 chown/chmod/restorecon


2.4 第四站:Plugin 'mysql_native_password' is not loaded——版本间的「代沟」

  • 5.7 主库用户使用 mysql_native_password
  • 8.4 默认改为 caching_sha2_password
  • 不再需要加载 mysql_native_password.so,错误的 plugin-load-add 反而导致旧方式失效

三、拨云见日:三大根本原因

  1. 证书不合规:缺少 SAN 的自签默认证书。
  2. 文件格式问题:BOM / CRLF / SELinux 权限。
  3. 插件差异:8.4 已内置 mysql_native_password,配置沿用 5.7 思维必翻车。

四、终极解决方案 (SOP)

4.1 签发带 SAN 的专属证书(从库)

# 生成 CSR mkdir -p /db01/mysql/ssl cat > /db01/mysql/ssl/server.cnf <<'EOF' [ req ] default_bits = 2048 prompt = no default_md = sha256 req_extensions = req_ext distinguished_name = dn [ dn ] C = XX ST = MyState L = MyCity O = MyCompany CN = db-slave-01 [ req_ext ] subjectAltName = @alt_names [ alt_names ] DNS.1 = db-slave-01 IP.1 = 10.0.1.20 EOF openssl genrsa -out /db01/mysql/ssl/server-key.pem 2048 openssl req -new -key /db01/mysql/ssl/server-key.pem \ -out /db01/mysql/ssl/server.csr -config /db01/mysql/ssl/server.cnf

主库签发

openssl x509 -req -in /tmp/server.csr \ -CA /path/to/ca.pem \ -CAkey /path/to/ca-key.pem \ -CAcreateserial \ -out /tmp/server-cert.pem \ -days 730 -sha256 \ -extensions req_ext -extfile /tmp/server.cnf

4.2 证书净化 & 权限

mkdir -p /db01/mysql/ssl_final for f in ca.pem server-cert.pem server-key.pem; do cat /tmp/$f > /db01/mysql/ssl_final/$f done chown -R mysql:mysql /db01/mysql/ssl_final chmod 700 /db01/mysql/ssl_final chmod 640 /db01/mysql/ssl_final/{ca.pem,server-cert.pem} chmod 600 /db01/mysql/ssl_final/server-key.pem restorecon -Rv /db01/mysql/ssl_final # SELinux

4.3 修订 my.cnf 并重启

[mysqld] port = 3307 datadir = /db01/mysql socket = /db01/mysql/mysql.sock log-error = /db01/mysql_logs/mysqld.log # 删除 plugin-load-add mysql_native_password = ON ssl-ca = /db01/mysql/ssl_final/ca.pem ssl-cert = /db01/mysql/ssl_final/server-cert.pem ssl-key = /db01/mysql/ssl_final/server-key.pem require_secure_transport = ON
systemctl restart mysqld mysql -uroot -p'***' -e "ALTER INSTANCE RELOAD TLS;"

五、总结与反思

  • 安全配置需先行:默认自签证书仅供测试,生产必须重签带 SAN 证书。
  • 日志是最终真相mysqld.log > openssl verify
  • 敬畏版本差异:升级必看 Release Notes,切忌经验主义。
  • 掌握底层排障技巧:如「文件净化」,有效隔离变量。

常见报错速查

报错关键字 场景 解决思路
Access denied + REQUIRE X509 未带客户端证书 --ssl-* 参数
certificate verify failed SAN 不匹配 重签证书
Invalid certificates BOM/CRLF/SELinux/权限 证书净化 + 权限检查
mysql_native_password not loaded 8.4 默认差异 删除 plugin-load-add

祝各位升级顺利,少踩(或不踩)坑!

最后修改时间:2025-08-22 09:53:26
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论