最近访客

同一时间更新同一行,数据库会发生什么?

在高并发系统中,我们经常会遇到这样的场景:
两个用户几乎在同一时间提交请求,更新了同一张表里的同一行数据
这时,数据库到底会发生什么?会报错吗?会死锁吗?

本文就从 MySQL InnoDB 的事务机制出发,带你搞清楚其中的原理。


一、事务与锁的关系

在 MySQL 中,每一个 UPDATE/DELETE/INSERT 操作,本质上都运行在 事务 中。

  • 显式事务:BEGIN ... COMMIT 包裹的事务,锁会一直持有到提交。

  • 隐式事务:单条 SQL 没有写事务语句,但 MySQL 会自动开启事务,在语句执行完后立即提交。

不管哪种事务,只要涉及数据修改,就会对目标行加上 行锁


二、同一时间更新同一行的场景

Session A(显式事务)

BEGIN;
UPDATE product_audit SET edit_record = 'xxx' WHERE id = 1;
-- 成功锁住 id=1
 
 

Session B(隐式事务)

 
UPDATE product_audit SET edit_record = 'zzz' WHERE id = 1;
-- 想要锁 id=1,但发现被 Session A 占用 → 进入等待

三、会发生死锁吗?

不会。
死锁的条件是 至少两个事务,互相等待对方的资源,形成环路。

在这里,A 和 B 都只在争抢 同一行 (id=1)

  • A 已经拿到锁

  • B 只能等待 A 释放

所以这不是死锁,而是 锁等待


四、可能的结果

  1. 正常等待
    如果 A 很快提交事务:

    • A 释放锁

    • B 拿到锁并执行更新

    • 两个事务都成功

  2. 等待超时
    如果 A 长时间不提交事务:

    • B 会一直等待

    • 等待超过 innodb_lock_wait_timeout(默认 50 秒),B 报错:

    • ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
  3. 不会发生死锁
    因为涉及的只是同一行,不存在循环依赖。


五、与“更新不同的行”对比

场景 锁情况 结果
更新同一行 两个事务争抢同一把锁 一个持有,另一个等待,可能超时
更新不同的行,但顺序不一致 A 先锁 id=1 等 id=2,B 先锁 id=2 等 id=1 出现循环等待 → 死锁

六、如何优化?

  1. 缩短事务时间
    尽快提交,减少锁等待。

  2. 合理设置超时时间
    根据业务场景调整 innodb_lock_wait_timeout

  3. 应用层重试机制
    遇到 Lock wait timeout 错误时,可以重试操作。


七、总结

  • 同一时间更新同一行 → 不会死锁,只会发生 锁等待,可能触发超时。

  • 更新不同的行,但顺序不一致 → 才可能出现死锁。

  • 高并发场景下,优化事务、控制锁范围、合理设计重试逻辑,才能让系统更稳健。


🔑 一句话总结:

更新同一行 → 锁等待;
更新不同的行(顺序不一致) → 死锁风险。

温馨提示: 本文最后更新于2025-09-11 17:17:15,若文章内容或图片失效,请留言或联系站长反馈!
本站资源均仅供学习和研究使用,请在下载后24小时内删除!
© 版权声明
THE END
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容