能,但不是“开箱即用”;需确保OceanBase运行在MySQL兼容模式、ThinkPHP使用pdo_mysql驱动、显式配置hostport=2883、charset=utf8mb4及正确用户名格式(user@tenant),并避免直连集群地址。

ThinkPHP 本身不原生支持 OceanBase,但可以通过复用 MySQL 协议栈 + 正确配置连接参数实现对接;直接套用默认 database.php 配置大概率失败,关键在驱动兼容性、字符集、时区和连接池行为。
ThinkPHP 能否直连 OceanBase?
能,但不是“开箱即用”。OceanBase 兼容 MySQL 协议(v5.7 或 v8.0 模式),ThinkPHP 的 mysql 类型驱动可复用,前提是:MySQL 客户端版本 ≥ 5.7、PDO 扩展启用、且 OceanBase 实例已开启 MySQL 兼容模式(ob_mysql_mode = true)。否则会报 SQLSTATE[HY000] [2002] Connection refused 或握手失败。
- OceanBase 必须运行在 MySQL 兼容模式下(非 Oracle 模式),可通过
SHOW VARIABLES LIKE 'ob_mysql_mode';确认返回ON - ThinkPHP 6+ 推荐使用
pdo_mysql扩展,而非mysqli;若用mysqli,需确保 PHP 编译时链接的 mysqlnd 版本 ≥ 5.7 - 连接时必须显式指定
'port' => '2883'(OceanBase 默认 MySQL 协议端口,非 3306)
database.php 中的关键配置项
以下字段不可省略或写错,否则初始化连接时会静默失败或查询乱码:
-
'type'必须为'mysql',不能填'oceanbase'(框架无该驱动) -
'hostname'填 OB Proxy 地址或单节点observerIP,不建议直连集群地址(需配合负载均衡) -
'hostport'必须设为2883,不是 3306 -
'charset'强烈建议设为'utf8mb4',并确认 OceanBase 租户级字符集也为utf8mb4(ALTER TENANT tenant_name CHARSET = utf8mb4;) -
'params'数组中需加入时区设置:PDO::ATTR_EMULATE_PREPARES => false和PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '+08:00'",否则时间字段可能偏移
示例片段:
立即学习“PHP免费学习笔记(深入)”;
return [
'type' => 'mysql',
'hostname' => '192.168.1.100',
'hostport' => '2883',
'database' => 'test_tenant',
'username' => 'root@test_tenant',
'password' => '',
'charset' => 'utf8mb4',
'prefix' => '',
'debug' => true,
'params' => [
\PDO::ATTR_EMULATE_PREPARES => false,
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '+08:00'",
],
];
多租户/多数据库场景下的 Db::connect() 动态切换
当一个 ThinkPHP 应用需同时访问多个 OceanBase 租户(如 tenant_a、tenant_b),不建议改写全局 database.php,而应使用 Db::connect() 按需建立隔离连接:
- 每个租户需独立配置
username格式:用户名@租户名(如'admin@sys'),不能只写'admin' - 连接后执行的 SQL 无法跨租户,
$db->name('table')中的表名必须属于当前连接租户下的库 - 避免在事务中混用多个
Db::connect()实例,OceanBase 不支持跨租户两阶段提交 - 连接字符串中不要带
database参数(即不指定库名),而应在 SQL 中显式写tenant_a.table_name或先USE tenant_a
示例:
$tenantA = Db::connect([
'type' => 'mysql',
'hostname' => '192.168.1.100',
'hostport' => '2883',
'database' => '',
'username' => 'app_user@tenant_a',
'password' => 'xxx',
'charset' => 'utf8mb4',
]);
$tenantB = Db::connect([
'type' => 'mysql',
'hostname' => '192.168.1.100',
'hostport' => '2883',
'database' => '',
'username' => 'app_user@tenant_b',
'password' => 'xxx',
'charset' => 'utf8mb4',
]);
性能测试前必须校准的三个点
OceanBase 对连接行为、SQL 解析、执行计划高度敏感,ThinkPHP 默认配置在压测中容易暴露瓶颈:
- 关闭
debug模式:生产环境开启debug会导致每次查询都记录完整 SQL 和 trace,CPU 消耗翻倍 - 禁用字段缓存:ThinkPHP 默认首次查表会缓存字段结构到
runtime/cache/,但 OceanBase 租户级 DDL 变更频繁,建议设'schema' => false避免缓存过期失效 - 连接池大小要匹配 OB 的
__min_full_resource_pool_memory:若 ThinkPHP 连接池设为 20,而 OB 单个资源池最小内存仅 2G,会导致大量连接被拒绝;建议初始按max_connections / 4设置 ThinkPHP 的'pool_size'
真正卡住的地方往往不是 SQL 写法,而是租户级 session 变量未对齐(比如 sql_mode)、OB Proxy 转发超时(需调大 proxy_sess_timeout)、或 PHP 进程内连接复用与 OB observer 的 idle timeout 冲突。这些细节不验证,压测数据就不可信。



















