一、背景与问题
在一次标准的数据库升级工作中,我们遇到了一个极具挑战性的场景:搭建 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反而导致旧方式失效
三、拨云见日:三大根本原因
- 证书不合规:缺少 SAN 的自签默认证书。
- 文件格式问题:BOM / CRLF / SELinux 权限。
- 插件差异: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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




