ThinkPHP 无法在 database.php 中配置或创建 OceanBase Cloud 租户,因其租户由云平台预分配并需通过 OCP 或 obclient 在 sys 租户下管理;正确做法是填入 OB Cloud 提供的连接地址、业务租户用户名(含@租户名#集群名)、指定 database 名及 utf8mb4 字符集,并启用持久连接以适配租户资源限制。

ThinkPHP 无法直接通过 database.php 配置 OceanBase Cloud 的租户,因为 OceanBase Cloud(即 OB Cloud)本质是托管服务,其连接地址、租户名、用户凭证均由云平台分配,且租户已预创建 —— 你不是“创建租户”,而是“连接并使用指定租户”。
为什么不能在 ThinkPHP 里执行 CREATE TENANT
ThinkPHP 是应用层框架,不参与 OceanBase 的资源编排。所有租户生命周期管理(CREATE RESOURCE UNIT、CREATE RESOURCE POOL、CREATE TENANT)必须在系统租户(root@sys)下,通过 obclient 或 OCP 控制台完成。ThinkPHP 连接的是业务租户(如 mq_t1),它只具备普通数据库操作权限,无 DBA 权限,执行 CREATE TENANT 会报错:ERROR 4620 (HY000): No privilege to create tenant。
- 租户创建属于集群级运维操作,需 sys 租户 +
root用户 + 集群资源空闲 - OB Cloud 控制台中“新建租户”按钮背后调用的是 OCP API,不是 SQL
- ThinkPHP 的
Db::execute()即使连上 sys 租户,也因权限隔离和安全策略被拦截
ThinkPHP 正确连接 OceanBase Cloud 租户的配置项
你需要把 OB Cloud 分配的「租户连接信息」填入 ThinkPHP 的数据库配置,关键不是“管理租户”,而是“精准指向租户内的 database”:
-
'hostname':填 OB Cloud 实例详情页的「连接地址」(如obcloud-xxx.ap-southeast-1.oceanbase.cloud),不是内网 IP -
'database':填租户内已存在的 database 名(如testdb),不是租户名;租户名体现在用户名里 -
'username':格式为用户名@租户名#集群名,例如admin@mq_t1#obcloud-xxx—— 缺少#集群名会导致认证失败 -
'password':对应用户的密码,不是 sys 租户密码 -
'hostport':固定为2881(MySQL 兼容模式端口),OB Cloud 不开放 2883(Oracle 模式)
示例配置片段(config/database.php):
立即学习“PHP免费学习笔记(深入)”;
'mysql' => [
'type' => 'mysql',
'hostname' => 'obcloud-xxx.ap-southeast-1.oceanbase.cloud',
'database' => 'testdb',
'username' => 'admin@mq_t1#obcloud-xxx',
'password' => 'your_secure_password',
'hostport' => '2881',
'charset' => 'utf8mb4',
'prefix' => '',
],
租户字符集与 collation 必须提前对齐
OB Cloud 创建租户时若选了 utf8mb4_bin 字符集,而 ThinkPHP 默认用 utf8mb4_general_ci 建表,会导致 COLLATION mismatch 错误,尤其在 JOIN 或 GROUP BY 时触发隐式转换失败。
- 确认租户默认字符集:
SELECT * FROM oceanbase.DBA_OB_TENANTS WHERE TENANT_NAME = 'mq_t1';查DEFAULT_COLLATION字段 - 在 ThinkPHP 迁移或建表时显式指定:
CHARSET=utf8mb4 COLLATE=utf8mb4_bin - 避免在
database.php中设'charset' => 'utf8'—— OceanBase 不支持utf8(仅utf8mb4)
连接池与长连接的实际影响
ThinkPHP 默认使用短连接(每次请求新建+关闭),但在 OB Cloud 场景下,频繁握手会放大网络延迟,且 OceanBase 租户的 max_connections 有硬上限(社区版默认 1000)。建议启用持久连接:
- 在配置中加
'params' => [\PDO::ATTR_PERSISTENT => true] - 但注意:TP 的
Db::close()对持久连接无效,连接由 PHP-FPM 进程池复用,需配合mysql.wait_timeout(OB Cloud 默认 28800 秒)调整 - 若用 Swoole/Workerman 长生命周期框架,必须手动管理连接生命周期,否则可能拿到过期连接
真正容易被忽略的点是:OB Cloud 租户的资源规格(CPU/内存)决定了并发连接数上限,而不是配置文件里的数字 —— 超限后新连接会被静默拒绝,日志里只显示 Connection refused,而非明确的 “too many connections”。



















