一、背景與問題
在一次標準的數據庫升級工作中,我們遇到了一個極具挑戰性的場景:搭建 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進行舉報,并提供相關證據,一經查實,墨天輪將立刻刪除相關內容。




