ThinkPHP 默认连不上 GaussDB(for MySQL) 是因 GaussDB 默认启用严格 SQL 模式(如 STRICT_TRANS_TABLES),导致 ThinkPHP 自动生成的非严格兼容 SQL(如 GROUP BY 非聚合字段、datetime 插入空字符串等)在执行阶段报错,而非连接失败;必须在 database.php 的 'params' 中显式设置 PDO::MYSQL_ATTR_INIT_COMMAND => "SET sql_mode = 'NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'" 并启用 PDO::ATTR_EMULATE_PREPARES => true 才能正常运行。

ThinkPHP 能直接连 GaussDB(for MySQL),但必须关掉 strict 模式,否则 INSERT ... ON DUPLICATE KEY UPDATE 会报错。
为什么 ThinkPHP 默认连不上 GaussDB(for MySQL)
GaussDB(for MySQL) 虽然兼容 MySQL 协议,但它底层是基于 PostgreSQL 改造的分布式数据库,SQL 行为更接近 MySQL 5.7+,但默认开启严格模式(sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION)时,会对 ThinkPHP 自动生成的某些 SQL 做额外校验,比如:
-
INSERT INTO ... SELECT ...中字段数量不完全匹配时直接拒绝执行 -
GROUP BY非聚合字段未出现在SELECT列表中时报错(MySQL 5.7 默认允许,GaussDB 默认不允许) -
datetime类型插入空字符串或非法时间时抛异常(ThinkPHP 的create_time自动填充可能触发)
这些不是连接失败,而是查询执行阶段报错,错误信息通常是:ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause 或类似。
ThinkPHP 6.x 数据库配置要点
在 config/database.php 中,关键修改项如下:
立即学习“PHP免费学习笔记(深入)”;
-
'hostname'填 GaussDB 实例的内网地址(如gaussdb-mysql-xxxxxx.gaussdb.rds.huaweicloud.com),不要用公网地址 -
'database'必须是创建时指定的、DBCOMPATIBILITY='M'的数据库名(不能是 template0 或 O/B 兼容模式) -
'hostname'和'port'确保能被服务器 telnet 通(华为云安全组要放行 3306) -
'params'中必须显式关闭严格模式:'params' => [ \PDO::ATTR_EMULATE_PREPARES => true, \PDO::MYSQL_ATTR_INIT_COMMAND => "SET sql_mode = 'NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';" ]
注意:\PDO::ATTR_EMULATE_PREPARES => true 是必须的,否则 GaussDB 的预处理协议兼容层可能返回字段元信息异常,导致 Db::name('user')->find() 返回空数组。
迁移时容易漏掉的 GaussDB M 模式配置
GaussDB 控制台创建数据库时,默认是 O(Oracle)兼容模式。ThinkPHP 连接前必须确认该数据库是 M 模式,否则连得上也跑不了业务 SQL:
- 建库语句必须带
DBCOMPATIBILITY='M',例如:CREATE DATABASE myapp_db ENCODING='UTF8' DBCOMPATIBILITY='M';
- 如果已有数据库是 O/B 模式,无法在线修改兼容模式,只能导出再重建
- 连接后执行
SELECT VERSION();应返回类似8.0.32-GaussDB(for MySQL),而非14.0(那是 PG 内核版本,说明连错了模式) - 部分 ThinkPHP 扩展(如多语言字段自动切换)依赖
INFORMATION_SCHEMA.COLUMNS的列名格式,M 模式下才和 MySQL 一致;B 模式下字段名会带双引号或大小写敏感,导致Db::field('name')失效
备份与事务行为差异
ThinkPHP 的 Db::transaction() 在 GaussDB 上能用,但要注意两点:
- GaussDB 不支持
SAVEPOINT嵌套回滚(即Db::startTrans()后再嵌套Db::startTrans()会失败),建议业务层避免多层事务包装 - 使用
Db::backup()(非官方扩展)或自定义 mysqldump 命令备份时,必须加--set-gtid-purged=OFF参数,否则恢复时报GTID_PURGED cannot be changed - 华为云控制台「自动备份」生成的是
.qp格式,不能直接用mysql命令恢复,需先用flexusrds工具解包
最常被忽略的是:GaussDB 的 autocommit 默认为 ON,但 ThinkPHP 的 Db::execute() 执行 DDL(如 ALTER TABLE)后,会隐式提交当前事务——这点和原生 MySQL 一致,但开发时容易误以为还能 rollback。



















