gue*_*tli 6 postgresql deadlock
在单元测试中,我们运行:
BEGIN;
TRUNCATE table1;
TRUNCATE table2;
...
UPDATE ...;
ROLLBACK;
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果 cron 作业启动并且该作业在 table1 和 table2 上运行,这会导致死锁。
DatabaseError: deadlock detected
DETAIL: Process 15815 waits for AccessExclusiveLock on relation 291262 of database 290999; blocked by process 16391.
Process 16391 waits for RowShareLock on relation 291431 of database 290999; blocked by process 15815.
Run Code Online (Sandbox Code Playgroud)
有没有办法将单元测试与 cron 作业隔离(以避免死锁)?
我们在 x86_64 linux 上运行 PostgreSQL 9.0.10
TRUNCATE
仅当确定没有其他会话同时使用该表时才应使用。否则DELETE
应该使用。它较慢(如果行数很大),但它旨在支持当前隔离模式规则内的并发访问。
该文档说:
TRUNCATE 在它操作的每个表上获取一个 ACCESS EXCLUSIVE 锁,这会阻止该表上的所有其他并发操作。当指定 RESTART IDENTITY 时,任何要重新启动的序列同样被独占锁定。如果需要对表进行并发访问,则应改用 DELETE 命令。
如果DELETE
的缓慢是不可接受的,为了 100% 确定地避免死锁,您需要将整个序列放入关键部分,无论是在单元测试中还是在 cron 作业中。通过在任何其他操作之前请求显式锁定来进入临界区,例如:
BEGIN
SELECT pg_advisory_xact_lock(1); -- (1 is arbitrary: choose any value reserved for this purpose by your apps)
TRUNCATE ...;
TRUNCATE ...;
...processing...
ROLLBACK;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6723 次 |
最近记录: |