“以一致的顺序获取锁“是预防死锁最核心、最有效的手段

"以一致的顺序获取锁"是预防死锁最核心、最有效的手段。要彻底理解它,我们可以从死锁产生的底层原理出发,再结合具体的代码实践来看。

1. 底层原理:破坏"循环等待"条件

从操作系统和数据库的并发控制原理来看,死锁的产生必须同时满足四个必要条件:互斥、占有和等待、不剥夺、循环等待

"以一致的顺序获取锁"的本质,就是从物理上破坏"循环等待"条件

假设有两个并发事务需要同时操作资源 A 和 资源 B:

  • 不一致的顺序(产生死锁)
    • 事务 1:先锁 A,再锁 B
    • 事务 2:先锁 B,再锁 A
    • 结果:事务 1 持有 A 等待 B,事务 2 持有 B 等待 A,形成闭环,互相卡死。
  • 一致的顺序(避免死锁)
    • 事务 1:先锁 A,再锁 B
    • 事务 2:也先锁 A,再锁 B
    • 结果:如果事务 1 先抢到了 A,事务 2 会在尝试锁 A 时直接被阻塞排队。等事务 1 执行完释放了 A 和 B,事务 2 才能继续。交叉加锁的路径被消除,死锁自然无法发生。

2. 在 PostgreSQL 中的具体实践

在实际的数据库表设计和业务代码中,"一致的顺序"通常体现在以下两个维度:

维度一:跨表操作时,固定表的访问顺序

如果你的业务逻辑需要同时更新多张表(例如订单表和库存表),必须在全局约定一个固定的访问路径(例如:永远先锁 orders 表,再锁 products 表)。

维度二:批量操作同表多行时,强制按主键排序

这是后端开发中最容易踩坑的场景。比如批量更新一批商品库存,如果直接按前端传来的 ID 顺序去加锁,极易引发死锁。

在 Python 后端中,正确的做法是在应用层先对 ID 列表进行排序,或者在 SQL 中强制指定顺序:

python 复制代码
# 假设 items 是从前端或上游拿到的待更新商品列表
# 错误做法:直接按原顺序加锁
# for item in items:
#     update_stock(item.id)

# 正确做法:在 Python 应用层按 ID 升序排序,确保所有并发请求拿锁顺序一致
items.sort(key=lambda x: x['id']) 

for item in items:
    # 在事务中执行更新
    cursor.execute("UPDATE products SET stock = stock - 1 WHERE id = %s", (item['id'],))

或者直接在 SQL 层面利用 SELECT ... FOR UPDATE 配合 ORDER BY 来预锁定资源:

sql 复制代码
BEGIN;
-- 核心:通过 ORDER BY id 强制按主键升序获取行级锁
SELECT * FROM products WHERE id IN (1, 5, 3) ORDER BY id ASC FOR UPDATE;
-- 此时 ID 为 1, 3, 5 的行已按顺序被锁定,后续执行更新绝对安全
UPDATE products SET stock = stock - 1 WHERE id IN (1, 5, 3);
COMMIT;

3. 进阶注意事项

  • 排序字段必须命中索引 :如果 ORDER BY 的字段没有索引,数据库可能会触发全表扫描或 filesort,导致锁范围扩大甚至锁升级,反而增加死锁风险。
  • 警惕隐式加锁 :除了显式的 UPDATESELECT FOR UPDATE,外键约束、UPSERTINSERT ... ON CONFLICT)等操作在底层也是逐行加锁的。如果并发事务处理的数据集有交集且传入顺序不同,同样会死锁。因此,在 Python 中写入数据前,养成先对数据集按唯一约束字段排序的习惯是非常必要的。
  • 应用层兜底 :即使设计了完美的加锁顺序,极端并发下仍可能有意外。建议在 Python 代码中捕获 PostgreSQL 的死锁错误码(40P01),并加入指数退避的重试机制。

相关推荐
打工仔折腾 AI2 小时前
Prometheus 告警推钉钉:从单群 Webhook 到跨网络 Alertmanager 实战
人工智能·后端·python·性能优化
Ivanqhz2 小时前
Ping-Pong 双缓冲
开发语言·人工智能·python·深度学习·mlir
三十岁老牛再出发2 小时前
9月18日总结
python·深度学习·机器学习
就叫你天选之人啦2 小时前
安装torch+vllm+flash_attn的prompt
人工智能·pytorch·python
wuyk5552 小时前
21.计数排序:不用比较的“空间换时间”排序算法
python·算法·排序算法
智码看视界2 小时前
第4篇:循环神经网络及其变体 LSTM/GRU 实战
python·自然语言处理·gru·lstm·循环神经网络·情感分析·梯度消失
Web3&Basketball2 小时前
Agent外传审计实战:3类失准事故拦截脚本
python·大模型·agent·性能调优·推理优化
何以解忧,唯有..3 小时前
Milvus 向量数据库的 DDL、DML、DQL 操作详解
python
罗狮粉 993 小时前
AI-Gateway — 面向 AI Agent 的本地 Runtime Gateway
人工智能·python·inscode·ai编程