跳转到主内容
极星编程网:以代码为星,赴技术山海!

Webman原生SQL查询方法_Webman多数据库读写分离实操【经验】

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

相关文章