mysql ssl连接必须在database_url中显式启用,doctrine默认不启用ssl,需追加?ssl=true(mysql原生驱动识别),否则走明文;ssl路径和开关只能通过url参数传递,doctrine.yaml中配置ssl_ca等选项会报错;证书路径须为容器/php进程可读的绝对路径,权限错误是常见失败原因。

MySQL SSL 连接必须在 DATABASE_URL 中显式启用
Doctrine 默认不启用 SSL,哪怕 MySQL 服务端已配置好证书,DATABASE_URL 不加参数就走明文连接。要强制走加密通道,必须在 URL 后追加 ?sslmode=require(PostgreSQL 风格)或更兼容的 ?ssl=true(MySQL 原生驱动识别)。实际生效依赖底层 PDO MySQL 驱动是否支持 PDO::MYSQL_ATTR_SSL_CA 等选项,而 Doctrine 仅通过 URL 参数透传控制逻辑。
常见错误现象:Connection refused 或 SSL connection error: protocol version mismatch,往往不是证书问题,而是 URL 没带 ssl=true 导致客户端压根没尝试握手。
-
DATABASE_URL示例(含 SSL):mysql://user:pass@127.0.0.1:3306/dbname?serverVersion=8.0&ssl=true - 若需双向认证(client cert),还需额外加
&sslcert=/path/to/client-cert.pem&sslkey=/path/to/client-key.pem&sslca=/path/to/ca-cert.pem - 路径必须是容器/PHP 进程可读的绝对路径;Docker 环境中注意卷挂载位置与路径一致性
doctrine.yaml 里不能配 SSL 路径,那是误导
config/packages/doctrine.yaml 文件里没有 ssl_ca、ssl_cert 这类键——这些是 PDO 底层选项,Doctrine DBAL 不提供 YAML 层面的映射。所有 SSL 相关路径和开关,只能通过 DATABASE_URL 查询参数传递,或在 PHP 代码中手动构造 Connection 实例时传入 driverOptions 数组。
试图在 doctrine.yaml 的 doctrine.dbal.url 下写死路径,或往 options: 下塞 PDO::MYSQL_ATTR_SSL_CA,会导致 Symfony 启动报错:The option "options" does not exist(因 url 模式下 options 被忽略)。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 正确做法:只在
.env的DATABASE_URL中用查询参数传 SSL 控制项 - 若必须动态控制(如 CI 环境切换 SSL 开关),可用环境变量拼接:
DATABASE_URL="mysql://...?${DB_SSL:+ssl=true}" - YAML 中唯一能影响连接行为的是
serverVersion,它决定 DQL 生成语法,和 SSL 无关
证书文件权限和路径错位是 80% 的失败原因
MySQL 客户端(即 PHP 的 PDO MySQL)要求证书文件对运行 Web 服务器的用户(如 www-data、apache 或容器内非 root 用户)**可读**,且路径必须为**绝对路径**。相对路径、符号链接未解析、SELinux 上下文限制、或挂载卷权限为 600 但属主不是 PHP 进程用户,都会静默失败——表现为连接超时或 SSL_CTX_set_default_verify_paths failed。
验证方式不是看 MySQL 服务端日志,而是进容器或服务器执行:php -r "var_dump(is_readable('/etc/mysql/ssl/ca-cert.pem'));"。返回 false 就得查属主和权限。
- 证书路径建议统一放
/etc/ssl/mysql/下,用chown www-data:www-data+chmod 644 - 避免把证书放在
var/或src/下——这些目录常被设为不可执行或受限读取 - Docker Compose 中记得显式设置
user: "www-data"并挂载证书卷,否则默认以 root 运行,读不到文件
测试 SSL 是否真生效,别只信 console 命令
php bin/console doctrine:database:create 成功不代表 SSL 生效——它可能 fallback 到非 SSL 连接(尤其当服务端允许混合模式时)。真正验证方式是抓包或查 MySQL 连接状态。
最简实操:进 MySQL 服务端执行 SHOW STATUS LIKE 'Ssl_cipher';,返回非空值(如 DHE-RSA-AES256-SHA)才说明当前连接用了 SSL;或者用 tcpdump -i lo port 3306 -w mysql.pcap 抓包后用 Wireshark 查 TLS 握手记录。
- 应用层快速判断:在任意 controller 里加
dump($this->getDoctrine()->getConnection()->getWrappedConnection()->getAttribute(\PDO::ATTR_SSL_CIPHER));,输出非空即通 - 若返回
null或报错SQLSTATE[HY000]: General error: PDO::getAttribute(): SQLSTATE[HY000]: General error,说明未启用或驱动不支持 - 注意:某些旧版 MySQL 扩展(如 php-mysqlnd










