update高并发卡住或报死锁,是因多请求同时修改同一行触发innodb行锁争用;thinkphp默认无重试和版本校验,需用乐观锁(version字段+where校验)或封装带退避的safeupdate方法。

为什么 UPDATE 在高并发下突然卡住或报死锁?
不是数据库扛不住,而是多请求同时想改同一行,InnoDB 加了行级写锁后互相等——比如两个请求都先 SELECT ... FOR UPDATE 锁住同一条订单记录,再各自执行 UPDATE,就形成死锁闭环。MySQL 被迫杀掉其中一个事务,抛出 Deadlock found when trying to get lock。
ThinkPHP 默认不处理这个,update() 方法直发 SQL,没重试、没版本校验,撞上就崩。
- 典型场景:秒杀下单、库存扣减、积分变更、后台批量审核
- 别指望加索引或拆表解决——根本问题在业务逻辑层缺乏并发控制
- 乐观锁比悲观锁(
FOR UPDATE)更适合 Web 请求模型:不锁行,靠数据版本判断是否被改过
用 where + version 字段实现乐观锁
核心思路:读取数据时带上 version 值,更新时只改 version 匹配的那条记录,并顺带把 version +1。若更新影响行为 0,说明已被别人抢先改过。
示例:用户余额扣减
// 查询时带上 version
$user = Db::name('user')->where('id', 123)->find();
// 执行更新,条件里带上 version,且 version 自增
$result = Db::name('user')
->where('id', 123)
->where('version', $user['version'])
->update([
'balance' => ['exp', 'balance - 100'],
'version' => ['exp', 'version + 1']
]);
if ($result === false) {
// 影响行为 0,说明 version 不匹配,数据已变
throw new Exception('数据已被修改,请重试');
}
-
version字段必须是整型,初始值为 0,每次成功更新都 +1 - 不能用
save()方法直接传数组更新,它会忽略where中的version条件;必须用update()配合显式where - 注意:ThinkPHP 6.1+ 的
update()支持exp表达式,但低版本需用Db::raw()
自动重试机制怎么加才不翻车?
手动捕获 Deadlock found when trying to get lock 或乐观锁失败后重试,但不能无限循环——得控次数、加退避、防雪崩。
推荐封装一个带重试的更新方法:
function safeUpdate($table, $pk, $id, $data, $maxRetry = 3) {
for ($i = 0; $i where($pk, $id)
->update($data);
if ($res !== false) return $res;
} catch (\Exception $e) {
if (strpos($e->getMessage(), 'Deadlock') !== false && $i
- 重试次数建议 ≤3,再多大概率是设计问题(比如热点 key 没分散)
- 必须加随机休眠,否则所有请求同步重试,反而加剧冲突
- 不要在事务外盲目重试——如果已在事务中,重试前需
Db::rollback(),否则下次beginTrans()会报错
为什么 selectForUpdate() 在 ThinkPHP 里要慎用?
ThinkPHP 的 lock(true) 确实能生成 SELECT ... FOR UPDATE,但它只对当前查询生效,后续 update() 是新语句,不继承锁。你得自己把锁和更新包进同一个事务,且保证中间不释放连接。
更麻烦的是:Web 请求生命周期短,数据库连接池复用频繁,FOR UPDATE 锁可能被意外释放或跨请求残留,导致锁表风险。
- 仅适用于极短逻辑(如“查+改”严格连续、无 I/O、无远程调用)
- 务必用
Db::startTrans()包裹整个流程,且commit()/rollback()显式控制 - 线上环境禁用长事务——哪怕只多 sleep(1),也可能让锁卡住其他请求几秒
- 比起
FOR UPDATE,乐观锁 + 重试在 ThinkPHP 生态里更稳、更易测、更少副作用
真正难的不是写重试代码,而是识别哪些字段必须强一致性(比如库存)、哪些可以最终一致(比如浏览数),然后分而治之。别让一个 version 字段,掩盖了业务建模的问题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











