Django使用select_for_update时PostgreSQL出现表锁而非行锁问题
问题原因
- 你看到的
relation类型锁是PostgreSQL的标准意向锁,属于RowExclusiveLock,不是锁住整张表的排他锁。所有行修改类操作(SELECT FOR UPDATE、UPDATE、DELETE等)都会自动在对应表上加这个轻量级表级锁,它只会阻塞ALTER TABLE、DROP TABLE、TRUNCATE这类DDL操作,完全不会阻塞其他事务对表内任意行的读写、行级加锁操作,不影响业务并发。 - 没有看到
tuple类型行锁的常见原因:- PostgreSQL的
pg_locks视图默认不会持久化展示无冲突的已持有行锁,只有当行锁出现争用,也就是有其他事务等待这行的锁时,才会在视图中明确展示tuple类型的锁记录 - 你在
SELECT FOR UPDATE后直接执行了DELETE,被标记为待删除的行的行锁记录会被PostgreSQL优化,不会一直保留在pg_locks的活跃展示列表中
- PostgreSQL的
验证方案
你可以通过以下操作确认没有加全表锁:
- 运行你给出的事务代码,在
sleep阶段新开一个数据库会话 - 执行更新同表其他行的SQL,比如
UPDATE my_model SET 字段名 = '测试值' WHERE pk = '5678' - 该SQL会立刻执行成功,不会被阻塞,即可证明仅你指定的pk=1234的行被锁定,不存在全表锁
内容的提问来源于stack exchange,提问作者Cowabunga
相关产品推荐
相关产品推荐

