mysql ssl证书配置失败主因是证书未被加载:ssl_ca必须置于[mysqld]段、用绝对路径、属主为mysql且权限600;mysql 8.0.28+强制要求subjectaltname(含dns/ip),缺失则静默跳过;证书过期、未重载tls或客户端缓存旧ca亦导致连接失败。

MySQL SSL证书配置失败,90%不是配错了,而是证书本身不被MySQL加载——它静默跳过,have_ssl显示DISABLED,SHOW STATUS LIKE 'Ssl_cipher'返回空,连错误日志都不报。
为什么ssl_ca写了却没生效?
MySQL启动时读不到ssl_ca文件,不会报错,只会降级为非SSL模式。常见原因有三个:
-
ssl-ca路径写在[client]或[mysql]段,必须挪到[mysqld]段才有效 - 路径用了相对路径(如
./ca.pem)或波浪号(~/ssl/ca.pem),MySQL只认绝对路径,例如/etc/mysql/ssl/ca.pem - 文件权限不是
600,或属主不是mysql用户(Linux下),644都可能加载失败
验证方式:用MySQL进程身份手动读取:sudo -u mysql cat /etc/mysql/ssl/ca.pem;若报错,说明权限或路径不对。
自签名证书为什么MySQL 8.0+直接拒绝?
MySQL 8.0.28+起强制校验subjectAltName(SAN)字段,旧脚本生成的证书若缺这个,mysqld启动不报错,但have_ssl始终是DISABLED。
- 生成CSR时必须显式加
subjectAltName,不能只靠CN;例如连接用db.example.com,就得包含DNS:db.example.com - 若还支持IP直连(如
10.0.1.5),必须同时写IP:10.0.1.5,漏一个就加载失败 - OpenSSL 3.0+可用
-addext "subjectAltName = DNS:db.example.com,IP:10.0.1.5";老版本得用配置文件,在[req_ext]段写明
检查命令:openssl x509 -in server-cert.pem -text -noout | grep -A1 "Subject Alternative Name",输出为空即为缺失。
客户端连不上,真是服务端证书问题吗?
先别动配置,直接查服务端证书是否真过期——MySQL不报“证书过期”,只抛笼统的SSL connection error: certificate verify failed。
- 登录MySQL服务器,运行:
openssl x509 -in /var/lib/mysql/ca.pem -text -noout | grep -E "(Not Before|Not After)" - 如果
Not After早于2026-08-12(当前日期),就是它了 - 云数据库(RDS/Aliyun/TencentDB)无法读文件,必须去控制台「SSL设置」页查
ValidTill字段
注意:SHOW VARIABLES LIKE 'ssl_cert_expire_date'仅MySQL 8.0.29+支持;老版本查不到就别等,直接看证书文件。
更新证书后客户端还是连不上?
证书换了,但MySQL进程没重载,或客户端缓存了旧CA,这两步漏一不可:
- 服务端执行:
ALTER INSTANCE RELOAD TLS;(MySQL 5.7.36+/8.0.16+),比重启mysqld更快;老版本只能service mysql restart - Java应用必须重启JVM,因为
truststore在启动时已加载;Python的pymysql不缓存,但若代码里硬编码了ssl_ca路径,要确认该路径指向新证书 - 命令行工具如
mysql -u root -p --ssl-ca=/path/to/new/ca.pem必须显式指定,否则可能沿用系统默认CA路径(如/etc/ssl/certs/ca-certificates.crt)
最容易被忽略的是:证书内容没问题,但路径、权限、SAN、重载、客户端缓存这五点只要卡住一个,就等于白换。











