SELECT是否阻止返回的行被删除?

时间:2018-02-16 04:22:45

标签: sql postgresql database-locking read-committed

说我有:

  1. T1:SELECT id FROM x WHERE timestamp < y(返回id = [1, 2, 3]
  2. T2:DELETE FROM x WHERE id = 1
  3. T1:SELECT timestamp, value FROM x WHERE id = 1
  4. READ-COMMITTED隔离。

    步骤3是否存在返回空结果的风险,或者步骤1是否获得某种锁定/快照以防止步骤2更改结果? (我假设REPEATABLE-READ会做我想要的,但这个问题是关于READ-COMMITTED)。

    我正在使用postgresql,但我对独立于数据库的答案感兴趣。例如,如果某些数据库阻止删除而其他数据库没有阻止删除,我想知道这一点。谢谢。

1 个答案:

答案 0 :(得分:1)

PostgreSQL案例:

在PostgreSQL中,读取一行并不会获得阻止同时删除行的锁:

  • 如果T2在步骤3之前提交,T1将看到其结果并返回空结果集。

  • 如果第3步在T2提交之前运行,则T2的结果尚不可见,查询将返回匹配的行。

一般情况:

数据库系统有不同的方式来提供事务隔离,行为将根据使用的方法而有所不同。

  • 某些数据库系统(如DB2或Microsoft SQL Server)会在读取行时锁定行以防止并发更新。

    在此类数据库系统上,myPojo.getMapAttrValue().put(key,value)将阻止,并且该行在步骤3中可见。

  • 大多数数据库系统使用某种多版本化,即在修改行的事务正在进行时,它们会保留旧版本的行。

    在此类数据库系统上,DELETE未被阻止,步骤3的结果将取决于T2是否已提交。

解决方案:

如果您正在寻找使所有数据库系统的行为具有确定性的解决方案,您可以使用更高的隔离级别,也可以通过指定DELETE来使用悲观锁定步骤1中的FOR UPDATE语句。然后步骤2将始终阻止。