证书确实过期了,执行 SHOW VARIABLES LIKE 'ssl_cert_expire_date' 可查证;若返回空或日期早于当前(如2026-06-14),即为过期,MySQL 版本需支持该变量。

先确认是不是证书真过期了,不是配置写错了
MySQL不会直接告诉你“证书过期”,只会报 ERROR 2026 (HY000): SSL connection error 或 certificate verify failed。90% 的握手失败根源在此,别急着改 my.cnf。
- 登录 MySQL 实例执行:
SHOW VARIABLES LIKE 'ssl_cert_expire_date';—— 如果返回空,或日期早于当前(比如显示2026-06-14),就是它了 - MySQL 版本 openssl x509 -in /var/lib/mysql/ca.pem -text -noout | grep -E "(Not Before|Not After)"
- 云数据库(RDS/AWS/腾讯云)不能 SSH 进去?去控制台「SSL 设置」页看
ValidTill字段,别翻日志猜
新证书必须带 subjectAltName,否则 MySQL 8.0+ 静默跳过
缺 subjectAltName 是升级或迁移后 SSL 失效的隐形杀手:MySQL 启动不报错,have_ssl 显示 DISABLED,SHOW STATUS LIKE 'Ssl_cipher'; 返回空——你根本意识不到证书被无视了。
- 生成时必须显式覆盖所有访问方式:
DNS:db.example.com、IP:10.0.1.5、IP:127.0.0.1、DNS:localhost - OpenSSL 3.0+ 示例:
openssl req -new -key server-key.pem -out server-req.csr -subj "/CN=db.example.com" -addext "subjectAltName = DNS:db.example.com,IP:10.0.1.5,IP:127.0.0.1" - 旧版 OpenSSL?得在
openssl.cnf里加[req_ext]段并写明subjectAltName
客户端连不上,用 --ssl-mode=VERIFY_CA 快速定位责任方
服务端证书更新后,客户端可能还在用旧 CA、缓存路径、或默认信任系统根证书。临时绕过验证能快速分清是服务端还是客户端的问题。
- 命令行测试:
mysql --ssl-mode=VERIFY_CA --ssl-ca=/etc/mysql/ssl/ca.pem -u user -h host -p - 如果报
unable to get local issuer certificate,说明客户端 CA 路径不对或文件损坏 - 只写
--ssl-mode=REQUIRED不带--ssl-ca,等于告诉 MySQL “只要加密,别管是谁”——生产环境禁用 - 路径必须是绝对路径:
~/ca.pem或./ca.pem在某些 shell 里会解析失败
DBeaver / JDBC / PDO 连接失败,CA 加载位置和格式各不相同
同一份 CA 证书,在不同客户端里填错位置等于没配。JVM 或 PHP 运行时加载失败,跟 MySQL 服务端完全无关。
- DBeaver:连接编辑页 → Driver properties → 找到
sslTrustCertificate,填绝对路径(如/home/user/certs/aliyun-rds-ca-cert.pem),同时确保useSSL=true且sslMode=REQUIRED - JDBC URL 必须显式传入:
trustCertificateKeyStoreUrl=file:/tmp/rds-ca.pem&trustCertificateKeyStorePassword=changeit;若用 PEM 格式,部分驱动支持sslTrustCertificate参数 - PDO:DSN 里必须带
ssl_mode=VERIFY_IDENTITY,仅ssl_mode=REQUIRED不够;PDO::MYSQL_ATTR_SSL_CA必须指向完整 bundle,Alpine 容器需手动挂载/etc/ssl/certs/ca-certificates.crt
最容易被忽略的是权限和路径:服务端 ssl-ca 文件必须属主 mysql、权限 600、路径绝对;客户端工具对路径解析更脆弱,相对路径、波浪号、符号链接基本都失效。证书内容再对,这两项错一个,就卡在握手第一秒。


















