Postgres并发DELETE RETURNING查询的行为

时间:2015-03-01 18:39:35

标签: database postgresql transactions locking

如果我有一个数据库事务,那就是:

DELETE FROM table WHERE id = ANY(ARRAY[id1, id2, id3,...]) RETURNING foo, bar;

if num_rows_returned != num_rows_in_array then
    rollback and return

Do stuff with deleted data...
Commit

我的理解是DELETE查询将锁定这些行,直到事务被提交或回滚。根据{{​​3}}:

  

自动对特定行进行独占行级锁定   更新或删除行时获取。锁定一直持续到   事务提交或回滚,就像表级锁一样。   行级锁不会影响数据查询;他们只阻止作家   到同一行。

我在postgres 9.1.13中使用默认的读取提交隔离级别

我会从中得知我应该没事,但我想确保这意味着以下事情是真的:

  • 除非先前的事务已回滚,否则只有一个事务可以从此表中删除并返回一行。
  • 这意味着"对删除的数据进行处理"每行只能进行一次。
  • 如果两个事务尝试同时执行上述冲突行,则始终成功(忽略系统故障),并且总会失败。
  • 当没有交叉的行时,并发事务可能会成功。
  • 如果事务无法删除并返回所有行,则它将回滚,因此不会删除任何行。例如,事务可能会尝试删除两行。一行已被另一个事务删除,但另一行可以免费返回。但是,由于已删除了一行,因此不能删除和处理另一行。只有在删除并返回所有指定的ID时,才会发生任何事情。

1 个答案:

答案 0 :(得分:1)

使用concurrency的正常概念,当进程/事务被锁定数据时失败,他们等待

DBMS以事务推进的方式实现执行,但只根据隔离级别查看来自其他事务的影响。 (只有在检测到死锁的情况下,事务才会中止,即使这样,它的实现执行也会再次开始,并且对于下一次执行或除了每个隔离级别之外的其他事务,查杀都不明显。)在SERIALIZABLE隔离级别下,这意味着数据库将更改,就好像所有事务都按某种顺序发生而没有重叠。其他级别允许事务看到其他事务的重叠实现执行的某些影响。

然而,对于PostgresSQL在SERIALIZABLE下,当事务尝试提交并且DBMS发现它将提供非序列化行为时,tranasaction将中止通知但不会自动重新启动。 (请注意,实现执行尝试访问锁定资源时,这 not 失败。)

(在9.1之前,PostgrSQL SERIALIZABLE没有给出SQL标准(序列化)行为:"为了保留传统的Serializable行为,现在应该请求可重复读取。")

锁定协议是实际执行执行如何交错以最大化吞吐量同时保持真实。所有锁定都会阻止实际重叠的实现执行访问,以实现明显的序列化执行。

交易代码

Explicit locking也只会导致等待。

您的问题并未反映出这一点。您似乎认为实现尝试访问锁定的资源会中止事务。事实并非如此。