tp5.1写操作报错主因是主库write配置无效或被误切至从库:write必须为一维数组、键名严格为host/port/database等,且不可在事务外被read_master或slave()干扰;需验证连接独立连通性并区分db门面与模型调用差异。

写操作报错,大概率不是读写分离本身出错,而是配置未生效或逻辑被绕过——TP5.1 的读写分离对“写操作”其实不干预,它只影响 find/select/get 这类查询方法。如果 insert/update/delete 报错,问题通常在主库连接或事务上下文上。
检查主库 write 配置是否完整有效
TP5.1 要求 write 必须是扁平一维数组(不能嵌套),且所有字段名必须准确。常见错误包括:
- 把
'write' => ['host' => '192.168.1.10']写成'write' => [['host' => '192.168.1.10']](二维结构,TP5 不识别) - 用错键名,比如写成
'hostname'或'server',TP5.1 只认'host'、'port'、'database'、'username'、'password' -
'database'名与从库不一致,虽不影响写操作,但若后续跨库 JOIN 或事务中混用,会触发 PDO 异常
确认当前不在事务中,且未被 read_master 干扰
TP5.1 的写操作本该走主库,但如果代码里手动调用了 ->slave() 或框架误判了上下文,就可能强行切到从库并报错(从库禁止写)。排查点:
- 检查是否有
Db::name('user')->slave()->insert(...)这类显式指定从库的写法 - 查看是否在事务块内执行写操作:
Db::startTrans(); ... Db::table()->insert(); ... Db::commit();—— 正常应无问题,但若事务未正确开启或已回滚,部分驱动会残留状态 - 确认
read_master => true没有被全局启用又未隔离:它虽只控制读路由,但若配置文件中误将 write 地址也填进了 slave 数组,可能引发连接复用混乱
验证 write 连接是否真能独立连通
别依赖“配置写了就通”,直接测试主库连接:
- 临时注释掉
'read'配置,只留'write',再执行一次 insert —— 如果成功,说明原配置中 read 结构或地址干扰了连接初始化 - 用命令行验证主库可访问:
mysql -h 192.168.1.10 -u your_user -p -D your_db,确认端口、权限、防火墙都正常 - 开启数据库日志:
'debug' => true,看报错前最后一条尝试连接的是哪个 host —— 日志里若显示连的是从库 IP,说明 write 配置根本没加载进来
留意模型与 Db 门面的差异
如果你用的是模型(如 UserModel::create(...)),注意 TP5.1 模型默认走 default 连接,不会自动识别 read/write 分离。除非你在模型里显式指定:
-
protected $connection = 'write';(需提前在 database.php 中定义名为 'write' 的独立连接) - 或者调用
Db::connect('write')->table(...)->insert()显式切换 - 直接用
Db::table(...)->insert()时,框架才真正走你配的 read/write 结构











