# ERROR 2026 SSL connection error：MySQL TLS 连接失败的修法

> MySQL 报 ERROR 2026 表示与服务器的 TLS 握手失败：证书验证不过、自动生成的自签名 CA、主机名不匹配，或者没有共同的 TLS 版本。

Source: https://ssl.sh/zh/errors/mysql-ssl-connection-error/
Last updated: 2026-11-10

**`ERROR 2026 (HY000): SSL connection error` 的意思是：MySQL 客户端没能和服务器完成 TLS 连接。** 后面的 OpenSSL 信息说明原因，最常见的是用你提供的 CA 验证不了服务器证书、主机名不匹配，或者客户端和服务器没有共同支持的 TLS 版本。

## 快速修复

多数情况下，换上和服务器证书匹配的 CA 文件就能连上。先查看服务器出示的证书（需要 OpenSSL 1.1.1 及以上）：

```bash
openssl s_client -starttls mysql -connect db.example.com:3306 </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -ext subjectAltName -enddate
```

然后用匹配的 CA 连接：

```bash
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 首次启动时如果没配置证书，会在数据目录自动生成[自签名](https://ssl.sh/zh/glossary/self-signed-certificate/) CA 和服务器证书。它们的名字是通用的，主机名验证必然失败。

- **确认：** subject 是 `MySQL_Server_..._Auto_Generated_Server_Certificate`。
- **修复：** 用[私有 CA](https://ssl.sh/zh/cookbook/private-ca/) 或公网 CA 签发一张 [SAN](https://ssl.sh/zh/glossary/san/) 包含主机名的服务器证书，再配置：

```ini
[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 验证开启。
