thinkphp 6 配置腾讯云 cynosdb 读写分离需同时满足 deploy=1、rw_separate=true、read为二维数组且与write参数完整一致;事务/锁查询强制走主节点,故障不自动降级,须手动兜底并确认控制台“读写分离”开关已启用。

腾讯云 CynosDB 是兼容 MySQL 协议的云原生数据库,支持一写多读、自动故障转移和秒级弹性扩缩容。但 ThinkPHP 本身不感知 CynosDB 的集群拓扑或高可用机制——它只按你写的配置连接数据库。想让读写分离生效、故障时降级可读,必须手动对齐 CynosDB 实例结构 + ThinkPHP 的路由规则,漏掉任一环节,查询就全走主节点。
ThinkPHP 6 配置 CynosDB 主从地址需满足 deploy + rw_separate + 数组套数组
CynosDB 控制台会提供一个「主实例地址」和多个「只读实例地址」(如 mydb-1234567890.cynosdbmysql.tencentcdb.com:3306),但直接填进 ThinkPHP 就失效。TP6 要求:
-
deploy必须为1,否则整个读写分离模块不会初始化 -
rw_separate必须为true(不是1或字符串"true") -
read必须是二维数组:哪怕只有一个只读实例,也得写成[['hostname' => 'mydb-ro-xxx.cynosdbmysql.tencentcdb.com', 'port' => 3306, 'username' => 'ro_user', 'password' => 'xxx', 'database' => 'mydb', 'charset' => 'utf8mb4']] -
write只能是单维数组,且必须包含完整参数;若漏掉charset或database,连接会失败 - 所有节点的
database名必须完全一致,CynosDB 不支持跨库 JOIN,否则报错
事务中或带锁查询强制走 CynosDB 主节点,无法绕过
CynosDB 的只读实例存在毫秒到秒级延迟,ThinkPHP 在事务或加锁场景下主动禁用读写分离,这是合理设计,不是 bug:
腾讯云跨账号资源迁移工具,支持将账号A的VPC、CLB、NAT、CVM、安全组等资源迁移至账号B,通过CCN云联网实现跨账号网络互通,提供自动扫描、配置生成、Terraform部署功能。
- 调用
Db::startTrans()后,所有select()、find()都走主节点,哪怕你写了->useReadConnection()也无效 -
->lock(true)、->where('id', 1)->find()带 FOR UPDATE 的隐式锁,同样强制主库 - 原生 SQL 如
Db::query("SELECT * FROM user FOR UPDATE")会被 TP 当作写意图,走主库 - 如果你需要“事务内强一致读”,只能接受主库压力;若只是普通读,应避免在事务里执行无关
SELECT
CynosDB 故障转移后,ThinkPHP 不自动重连从库,需手动兜底
CynosDB 主节点宕机时,控制台会自动将某个只读节点升为主,但 ThinkPHP 不知道这件事——它的 read 配置仍是旧地址,write 地址已不可达。此时:
-
INSERT/UPDATE/DELETE会抛出PDOException: Connection refused,无法自动切到新主 -
SELECT查询仍尝试连旧只读地址,可能成功(如果该节点未被升主),也可能失败(如果已被接管) - 没有内置心跳或健康检查,
read列表轮询不跳过宕机节点,每次都会超时再试下一个 - 真正可行的兜底方式是捕获异常后,显式切到备用连接:
db('cynosdb_backup')->table('user')->select(),前提是已在connections中预定义好备用配置
调试时别信 getLastSql(),要看连接日志或 CynosDB 的 SHOW PROCESSLIST
getLastSql() 只返回 SQL 字符串,完全不体现执行节点。你以为走了从库,其实查的是主库;以为失败了,其实是连上了但慢得像卡住。验证是否真走 CynosDB 只读实例,只有两个可靠办法:
- 登录 CynosDB 只读实例,在命令行执行
SHOW PROCESSLIST;,过滤你的应用服务器 IP,看是否有活跃的SELECT连接 - 在
think/db/Connection.php的connect()方法开头加一行日志:file_put_contents('/tmp/db.log', "host: {$config['hostname']}, isRead: {$isRead}\n", FILE_APPEND); - 不要依赖
Db::connect('cynosdb_slave')测试——它绕过了读写分离逻辑,连的是固定地址,不能代表真实路由行为
最易被忽略的一点:CynosDB 的只读地址默认不开启「读写分离代理」,有些地域需在控制台手动开启「读写分离开关」并绑定只读节点,否则即使 ThinkPHP 配对了,请求也会被代理层转回主库。这个开关不在数据库参数里,而在 CynosDB 实例的「参数设置 → 网络与安全」中,名字叫「读写分离」,状态必须是「启用」。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










