温馨提示×

温馨提示×

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

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

为何数据库Lock锁会死锁

发布时间:2026-11-02 22:20:07 来源:亿速云 阅读:98 作者:小樊 栏目:数据库

数据库中的 Lock(锁)死锁 本质上是因为 多个事务相互等待对方持有的锁,形成一个闭环,导致谁都无法继续执行。下面从原理、常见原因和示例三个层面说明。


一、死锁的基本原理

在数据库中:

  • 事务 A 持有资源 X 的锁,想要资源 Y 的锁
  • 事务 B 持有资源 Y 的锁,想要资源 X 的锁

此时:

  • A 等 B 释放 Y
  • B 等 A 释放 X

双方都不会主动退让 → 死锁(Deadlock)

数据库通常会:

  • 检测死锁
  • 选择一个事务回滚(牺牲者)
  • 另一个事务继续执行

二、常见导致死锁的原因

1️⃣ 加锁顺序不一致(最常见)

事务A:先锁 表1,再锁 表2
事务B:先锁 表2,再锁 表1

并发时极易形成环。

✅ 解决:统一加锁顺序


2️⃣ 不同事务并发更新多行数据

-- 事务A
UPDATE account SET balance=... WHERE id=1;
UPDATE account SET balance=... WHERE id=2;

-- 事务B
UPDATE account SET balance=... WHERE id=2;
UPDATE account SET balance=... WHERE id=1;

行锁也可能死锁。


3️⃣ 锁粒度升级(行锁 → 表锁)

例如:

  • 大量行锁
  • 触发锁升级
  • 多个事务竞争表锁

在 SQL Server、Oracle 中较常见。


4️⃣ 隐式锁(你没意识到加了锁)

如:

  • SELECT ... FOR UPDATE
  • 外键检查自动加锁
  • 唯一索引冲突重试

5️⃣ 长事务 + 高并发

事务越长:

  • 持锁时间越久
  • 冲突概率越高
  • 死锁概率越大

三、一个经典死锁示例(MySQL)

-- 事务A
BEGIN;
UPDATE users SET name='A' WHERE id=1;

-- 事务B
BEGIN;
UPDATE users SET name='B' WHERE id=2;

-- 事务A
UPDATE users SET name='A' WHERE id=2; -- 等待B

-- 事务B
UPDATE users SET name='B' WHERE id=1; -- 等待A

结果:死锁


四、如何避免死锁?

✅ 最佳实践:

  1. 统一资源访问顺序
  2. 尽量缩短事务
  3. 减少锁范围(避免全表更新)
  4. 使用合适的隔离级别
  5. 捕获死锁异常并重试
  6. 避免用户交互在事务中

五、一句话总结

数据库 Lock 死锁,是因为多个事务“互相等对方的锁”,形成无法打破的等待环。

如果你愿意,我可以:

  • 用 MySQL / Oracle / PostgreSQL 具体例子讲
  • 分析你实际 SQL 死锁日志
  • 讲 如何定位死锁(SHOW ENGINE INNODB STATUS 等)

你可以直接贴场景。

向AI问一下细节

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

AI
助
手