Webman 不支持自动读写分离,需手动指定连接名;原生 SQL 查询必须显式绑定从库连接,否则默认走主库导致压力飙升,且不解析 SQL 类型自动切库。
Webman 不支持自动读写分离,必须手动指定连接名调用不同数据库实例;原生 SQL 查询需显式绑定连接,否则默认走
配置的主库,极易造成从库查询被发到主库、主库压力飙升。
Db::select() 必须带 connection 实例,不能直接调用
很多人写
,结果发现慢得离谱、监控里全是主库查询——这是因为没指定连接,它默认用了
连接,也就是你配置里的主库。读操作想走从库,就得先拿到从库连接实例。
正确写法是:
返回的是独立的
实例,后续所有方法(
、
、
)都绑定该连接
错误写法:
或
混用(
是查询构建器,
是原生入口,二者不共享连接上下文)
读写分离要靠多连接配置 + 业务层路由,不是框架自动识别 SQL 类型
Webman 没有 SQL 解析器,不会根据
或
自动切库。所谓“读写分离”,本质是你在代码里人为控制:写走
,读走
。
配置两个连接:
(
和
可空,Webman 不识别这个字段)和
,两者 host/port/database 全部不同
事务内必须全部使用同一连接,跨连接
无效,会各自开启、无法回滚
不要在同一个请求里混用多个连接查同一张逻辑表(比如用户信息既从
查又从
查),主从延迟会导致数据不一致
原生查询传参必须用 ? 占位符,别拼字符串
用
执行原生 SQL 时,如果把变量直接拼进 SQL 字符串,不仅有 SQL 注入风险,还会让 PDO 缓存失效、执行计划无法复用。
安全写法:
危险写法:
—— 单引号不防注入,双引号变量插值更危险
注意:占位符只支持
,不支持命名参数(如
),否则报
从库查询前务必确认主从延迟,否则查到脏数据
MySQL 主从复制有天然延迟,尤其在批量导入或大事务后。直接查从库可能拿到过期状态,比如用户刚注册就去查“是否已存在”,返回 false 导致重复注册。
简单判断延迟:
看
,>1 秒就得警惕
强一致性读(如订单详情、用户资料)应强制走主库:
非关键路径(如文章列表、统计看板)才适合走从库,且建议加
隔离级别防止幻读
最常被忽略的一点:Webman 的每个 worker 进程启动时会初始化一次数据库连接池,但连接本身不感知主从状态变化。如果从库宕机或延迟突增,框架不会自动降级或切换,得靠你在业务层加心跳探测或失败重试逻辑。
defaultDb::select("SELECT * FROM users")defaultDb::connection('mysql_slave')->select("SELECT * FROM users WHERE status = ?", [$status])Db::connection()Illuminate\Database\ConnectionselectinsertupdateDb::select(...)Db::connection('mysql_slave')->table(...)->get()table()select()INSERTSELECTmysql_mastermysql_slavemysql_master'read' => []'write' => []mysql_slavebeginTransaction()mysql_mastermysql_slaveDb::connection(...)->select()Db::connection('mysql_slave')->select("SELECT id, name FROM users WHERE type = ? AND created_at > ?", [$type, $since])"... WHERE type = '$type'"?:typeInvalid parameter numberSHOW SLAVE STATUS\GSeconds_Behind_MasterDb::connection('mysql_master')->table(...)->find($id)READ COMMITTED