You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带锁的记录更新(不存在则插入)并判断锁状态?

问题分析与实现方案

你遇到的核心问题是对MySQL LOCK TABLE的返回逻辑理解有误——这个语句不会返回布尔值表示锁是否获取成功:它执行成功就返回正常状态,只有当无法获取锁(比如超时、权限不足)时才会抛出错误,这就是并发场景下你看到它始终返回"成功"的原因。

符合你需求的正确执行流程

按照你指定的"先更新,无影响则锁表插入"逻辑,正确的实现步骤如下:

  1. 执行更新语句并获取影响行数
    UPDATE x SET y=1 WHERE id=5;
    
  2. 根据影响行数分支处理:
    • 若影响行数>0:流程结束
    • 若影响行数=0:执行锁表插入逻辑:
      -- 对表x加写锁,确保当前会话独占写入权限
      LOCK TABLE x WRITE;
      -- 锁表后必须再次检查记录是否存在(并发场景下的关键校验)
      SELECT COUNT(*) FROM x WHERE id=5;
      -- 确认记录仍不存在时执行插入
      IF COUNT(*) = 0 THEN
          INSERT INTO x(id, y) VALUES(5, 1);
      END IF;
      -- 释放表锁
      UNLOCK TABLES;
      

必须注意的细节

  • 锁表后的二次检查不可省略:在你执行完UPDATE到获取锁的这段窗口,可能有其他会话已经插入了目标记录,直接插入会触发主键/唯一键冲突,所以必须在锁表后再次校验。
  • 关于LOCK TABLE的行为:MySQL的表锁默认是阻塞式的(除非设置LOCK TABLES ... NOWAIT),如果表已被其他会话锁定,当前会话会进入等待,直到获取锁或超时抛出错误,不会返回"false"。

内容的提问来源于stack exchange,提问作者John Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:25:14