当在同一个表上同时执行其他更复杂的语句时,触发器中执行的简单UPDATE
和DELETE
语句是否会导致死锁或回滚?
UPDATE "s_mat"
SET "req_st" = my_st, "l_upd" = retr
WHERE "req_id" = my_id;
DELETE FROM "mat" WHERE "req_id" = my_id;
我是否应该预测这些陈述的潜在deadlock_detected
或transaction_rollback
例外?
答案 0 :(得分:1)
基本上是的。如果两个触发器同时运行,请将它们称为t1和t2:
t1 t2
update row x
update row y
delete row y
delete row x
这会陷入僵局。 Postgres自动检测条件并中止除一个竞争交易之外的所有交易。 Details in the manual.
如果您的所有代码都处理相同顺序中的行,则不会发生这种情况。但有时这不能保证。
如果您在使用独占锁处理的所有行上取出manual locks,则可以大大减少死锁的可能性。
确定,您需要使用SERIALIZABLE
transaction isolation。您必须为序列化失败准备代码,并在这种情况下重试。
请注意,可序列化模式下的事务较慢,只应在必要时使用。如果您没有遇到繁重的并发负载或者代码中没有严格的语句组合,那么您可以使用默认(更快)READ COMMITTED
隔离级别。
优化代码性能并最大限度地减少竞争条件的机会窗口可以采用 long 方式。除了始终以相同的顺序处理行之外,您还可以使用data-modifying CTEs将UPDATE
和DELETE
组合在一个语句中,该语句可能会因并发操作而死锁。不排除竞争条件,但最小化死锁的时间范围。
详细示例:
PostgreSQL: using foreign keys, delete parent if it's not referenced by any other child