thinkphp数据库集群需通过预定义connections、deploy+rw_separate双开关主从分离、分键管理多业务库及.env仅变量注入四步实现。必须完整声明各节点连接,字符集统一,键名仅限小写字母与下划线;主连接设deploy=1且rw_separate=true;读写数组维度严格限定;跨库查询需手动分查合并。

ThinkPHP 的数据库集群连接不是简单堆叠多个地址,而是通过明确的主从结构、预定义连接和显式路由三者协同实现。配置写法稍有偏差,轻则读写错乱,重则连接失败或中文乱码。
一、必须用 connections 预定义全部节点
所有参与集群的数据库(主库、从库、日志库、报表库)都必须在 config/database.php 的 connections 数组中完整声明,不能靠运行时拼接。每个连接需独立键名,仅限小写字母与下划线,例如 mysql_master、mysql_slave1、report_db。
- 每个连接必须显式写明 'type' => 'mysql',漏掉会触发驱动误判,报 Class 'PDO' not found
- 必需字段一个不能少:hostname、database、username、password、charset
- 字符集必须统一,比如主库设 'charset' => 'utf8mb4',所有从库也得一致,否则 emoji 插入失败
- 禁止使用点号(如 log.db)或大写(如 LogDB),否则 Db::connect('log.db') 直接抛异常
二、主从分离需 deploy + rw_separate 双开关
读写分离不是自动识别 SQL 类型,必须手动开启机制并严格配对参数:
- 在主连接(如 mysql_master)配置块中添加 'deploy' => 1 —— 这是总闸门,缺了整个读写分离逻辑不生效
- 同时设置 'rw_separate' => true,但仅当 deploy === 1 时才起作用
- write 必须是一维数组,例如 ['hostname' => '192.168.1.10'];若写成二维,框架启动即报错
- read 必须是二维数组,例如 [['hostname' => '192.168.1.11'], ['hostname' => '192.168.1.12']];若写成一维,框架静默回退主库
- 所有读操作必须主动调用 useReadConnection() 或显式用 Db::connect('mysql_slave1'),否则默认走主库
三、多业务库建议分键管理,避免混用
不同业务场景(如用户主数据、操作日志、统计报表)应各自拥有专属连接键名,并在代码中显式调用,不依赖全局默认:
- 定义 mysql_log 专用于日志写入,可加 'write_master' => false 防止意外触发主库
- 定义 report_cluster 指向只读报表集群,其 charset 和 prefix 可与主库不同
- 跨库查询不支持自动 JOIN,例如查用户+其登录日志,需手动分两次:
→ Db::connect('mysql_master')->table('user')->select()
→ Db::connect('mysql_log')->table('login_log')->where('user_id', 'in', $ids)->select()
再在 PHP 层合并,注意重命名同名字段(如两个表都有 id)
四、.env 仅作变量注入,不替代 connections 结构
.env 文件无法定义数组或嵌套结构,只能提供扁平变量,用于填充 connections 中的值:
- .env 写法正确示例:
database2_hostname=192.168.1.11
database2_database=log_db - database.php 中对应引用:
'hostname' => env('database2_hostname', '127.0.0.1')
'database' => env('database2_database', '') - 禁止在 .env 中写 DATABASE2.HOSTNAME=... 或 connections[log_db][hostname]=...,这些语法无效
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











