温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

MVCC如何降低死锁概率

发布时间:2026-09-09 20:26:58 来源:亿速云 阅读:91 作者:小樊 栏目:数据库

MVCC(多版本并发控制,Multi-Version Concurrency Control)之所以能降低死锁概率,核心原因在于:它让“读”不阻塞“写”、“写”也不阻塞“读”,从而减少事务之间因互相等待锁而产生的循环依赖。

下面从原理到机制具体说明。


一、死锁为什么会发生?

死锁通常满足四个条件:

  1. 互斥
  2. 持有并等待
  3. 不可抢占
  4. 循环等待

在数据库里,死锁最常见于:

  • 事务 A 锁了行 1,想锁行 2
  • 事务 B 锁了行 2,想锁行 1

→ 互相阻塞,形成循环等待。


二、MVCC 如何减少这种情况?

1. 读操作默认不加锁(快照读)

在 MVCC 中:

  • SELECT(普通读)读取的是历史快照版本
  • 不需要加共享锁(S 锁)

✅ 效果:

  • 读不阻塞写
  • 写不阻塞读
  • 减少“读–写”之间的锁竞争

➡ 大量读事务不会参与锁等待,自然降低死锁概率。


2. 写操作只锁“当前版本”

MVCC 中:

  • 写操作(UPDATE / DELETE)只锁最新版本的行
  • 不会因旧版本被读而阻塞

对比:

  • 无 MVCC:读加 S 锁 → 写要等读释放
  • 有 MVCC:读用快照 → 写直接进行

➡ 锁的持有时间更短,冲突窗口更小。


3. 减少“锁升级”和“锁扩散”

在一些数据库中:

  • 行锁升级为表锁会增加死锁风险
  • MVCC 让读不依赖锁,降低锁数量

➡ 锁粒度更细、锁更少,死锁更难形成。


4. 事务视图隔离,避免不必要冲突

MVCC 通过:

  • 事务 ID
  • 版本链
  • ReadView(如 MySQL InnoDB)

让不同事务看到不同版本数据。

✅ 即使数据在并发修改:

  • 读事务不感知写
  • 写事务不感知读

➡ 减少了“为了一致性而互相等待”的场景。


三、MVCC 不能完全避免死锁

需要注意:

  • 写–写冲突仍然存在
  • SELECT ... FOR UPDATE 等当前读仍会加锁

示例仍可能死锁:

-- 事务 A
UPDATE account SET money=money-1 WHERE id=1;
UPDATE account SET money=money+1 WHERE id=2;

-- 事务 B
UPDATE account SET money=money-1 WHERE id=2;
UPDATE account SET money=money+1 WHERE id=1;

➡ MVCC 降低概率,但不消除死锁。


四、总结一句话

MVCC 通过“读不加锁、读写不互斥、缩短锁持有时间”,显著减少了事务间因锁等待形成的循环依赖,从而降低死锁概率。

如果你愿意,我也可以结合 MySQL InnoDB / PostgreSQL 的具体实现来对比说明。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手