邮件和其他协议
ERROR 2026 SSL connection error:MySQL TLS 连接失败的修法
ERROR 2026 (HY000): SSL connection error: error:0A000086:SSL routines::certificate verify failedERROR 2026 (HY000): SSL connection error 的意思是:MySQL 客户端没能和服务器完成 TLS 连接。 后面的 OpenSSL 信息说明原因,最常见的是用你提供的 CA 验证不了服务器证书、主机名不匹配,或者客户端和服务器没有共同支持的 TLS 版本。
快速修复
多数情况下,换上和服务器证书匹配的 CA 文件就能连上。先查看服务器出示的证书(需要 OpenSSL 1.1.1 及以上):
openssl s_client -starttls mysql -connect db.example.com:3306 </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -ext subjectAltName -enddate
然后用匹配的 CA 连接:
mysql -h db.example.com -u app -p --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/certs/db-ca.pem
- 签发者是
MySQL_Server_..._Auto_Generated_CA_Certificate: 服务器用的是自动生成的证书;VERIFY_CA 用它的ca.pem,要 VERIFY_IDENTITY 就得换正式证书。 - 签发者是云厂商的 CA: 从云厂商下载这个 CA。
原因
最常见的是前 3 种:CA 文件不对、自动生成的证书过不了主机名验证、双方没有共同的 TLS 版本。
1. CA 文件不对或没提供
- 确认: 在 VERIFY_CA 或 VERIFY_IDENTITY 下报
certificate verify failed;上面看到的签发者不是--ssl-ca里的 CA。 - 修复: 使用该签发者的根证书。阿里云 RDS、腾讯云 MySQL、AWS RDS、Azure 等托管数据库,在实例的 SSL 设置页或官方文档里下载 CA 证书。
2. 自动生成的证书遇上 VERIFY_IDENTITY
MySQL Server 首次启动时如果没配置证书,会在数据目录自动生成自签名 CA 和服务器证书。它们的名字是通用的,主机名验证必然失败。
- 确认: subject 是
MySQL_Server_..._Auto_Generated_Server_Certificate。 - 修复: 用私有 CA 或公网 CA 签发一张 SAN 包含主机名的服务器证书,再配置:
[mysqld]
ssl_ca = /etc/mysql/ssl/ca.pem
ssl_cert = /etc/mysql/ssl/server-cert.pem
ssl_key = /etc/mysql/ssl/server-key.pem
require_secure_transport = ON
MySQL 8.0.16 起可以执行 ALTER INSTANCE RELOAD TLS,不重启就加载新文件。
3. 没有共同的 TLS 版本
- 确认: 报错里有
unsupported protocol或no protocols available;服务器是用旧 TLS 库编译的 5.6/5.7 老版本。 - 修复: 升级服务器,或在支持的版本上设置
tls_version=TLSv1.2,TLSv1.3。
4. 证书过期
自动生成的证书有效期很长,但你自己安装的证书可能会过期。
- 修复: 续期、替换文件后执行
ALTER INSTANCE RELOAD TLS(8.0.16+)或重启。
5. 服务器没开 TLS
- 确认: 报
SSL connection error: SSL is required but the server doesn't support it。 - 修复: 给服务器配置证书;用
SHOW VARIABLES LIKE '%ssl%';检查,客户端里用\s查看当前使用的加密套件。
各环境修法
JDBC、PyMySQL、PDO 和 MariaDB 客户端都要做两件事:指定正确的 CA 文件,打开主机名验证。
JDBC(Connector/J 8.x): jdbc:mysql://db.example.com:3306/app?sslMode=VERIFY_IDENTITY&trustCertificateKeyStoreUrl=file:/path/truststore.p12&trustCertificateKeyStorePassword=...,用 keytool -importcert 导入 CA。
Python(PyMySQL / mysqlclient): 传 ssl={"ca": "/path/db-ca.pem"},并开启主机名检查(PyMySQL 用 ssl_verify_identity=True)。
PHP(PDO): PDO::MYSQL_ATTR_SSL_CA => '/path/db-ca.pem',保持 PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT 开启。
MariaDB 客户端: 用 --ssl-ca 配合 --ssl-verify-server-cert 做身份检查。
Docker: 把 CA 挂载进应用容器,数据库证书文件放在卷上,容器重建后不丢失。
宝塔面板安装的 MySQL: 默认没有为客户端连接配置正式证书,远程连接通常落在自动生成的证书上。需要加密的远程访问时,按上文配置证书,并在面板安全设置里只对应用服务器的 IP 放行 3306 端口。
国内云数据库内网连接: 同一 VPC 内用内网地址连接时,确认云厂商的证书覆盖了你使用的连接地址;不覆盖时按云厂商文档选择 VERIFY_CA 或使用证书覆盖的地址。
不要这样做
这些做法要么放弃了服务器身份验证,要么把数据库暴露给公网。
- 为了消除验证错误退回
--ssl-mode=REQUIRED或PREFERRED。 连接加密了,但服务器身份没有验证。 - 在生产环境的驱动里设置
verifyServerCertificate=false、trustServerCertificate=true之类的选项。 - 排查时把 3306 端口暴露到公网。 用安全组限制访问,并保持 TLS 验证开启。
常见问题
MySQL 的 ssl-mode 各个取值是什么意思?
ssl-mode 有 5 个取值,只有 VERIFY_CA 和 VERIFY_IDENTITY 会验证服务器证书。DISABLED:不用 TLS。PREFERRED(默认):服务器支持就用 TLS,不验证。REQUIRED:必须 TLS,但不验证证书。VERIFY_CA:用 --ssl-ca 验证证书。VERIFY_IDENTITY:再检查主机名和证书是否匹配。
MySQL 自动生成的证书,CA 文件在哪里?
在服务器数据目录里,叫 ca.pem,旁边是 server-cert.pem 和 server-key.pem。VERIFY_CA 时把 ca.pem 复制给客户端;要用 VERIFY_IDENTITY,就把这些文件换成 SAN 包含客户端所用主机名的证书。宝塔安装的 MySQL 数据目录一般在 /www/server/data。
Java 报 No appropriate protocol,是同一个问题吗?
是同一类问题,即 Java 里的 TLS 版本不匹配:服务器只提供 TLS 1.0/1.1,而新版 JDK 默认禁用了它们。升级服务器或调整其 TLS 设置,让它支持 TLS 1.2 或 1.3;见 Java SSLHandshakeException。