为什么无法通过显式锁定查询语法获取谓词锁

时间:2015-10-08 19:13:27

标签: mysql sql-server oracle postgresql transactions

大多数RDBMS允许在所选行上获取共享锁独占锁。例如,PostgreSQL有这样的语法:

SELECT * 
FROM post 
WHERE id=10 
FOR SHARE;

使用FOR SHARE,即使在READ_COMMITTED隔离级别,我们也可以获取共享锁,并且可以防止不可重复的读取现象,而无需实际使用REPEATABLE_READ事务隔离。

但是为了防止幻像读取,SERIALIZABLE是唯一的方法。为什么没有明确的锁定语法来获取谓词锁?

据我所知,我不记得在Oracle,SQL Server,MySQL或PostgreSQL中看过任何这样的构造。

2 个答案:

答案 0 :(得分:1)

在PostreSQL中,Serializable隔离级别基于所谓的Serializable Snapshot Isolation,它使用谓词锁不用于实际锁定,而是用于监视可能产生序列化异常的条件。此机制仅适用于Serializable级别;没有办法在较低级别使用谓词锁。

但是为了防止幻像读取,你实际上只需要PostgreSQL中的可重复读取隔离级别(尽管SQL标准对隔离级别有所说明)。有关详细信息,请参阅the documentation

至于Oracle,它根本没有谓词锁。它的Serializable隔离级别使用快照隔离(与PostgreSQL中的Repeatable Read相同),可以防止幻像读取但允许other serialization anomalies

我没有关于SQL Server和MySQL的信息。

答案 1 :(得分:1)

标准没有指定谓词锁,或者必须使用谓词锁来实现SERIALIZABLE。它只指定SERIALIZABLE必须防止的异常......并且大多数DBMS实际上并不完全符合那些。

在PostgreSQL的情况下,没有明确的谓词锁定语法,因为没有谓词锁。 PostgreSQL使用更像SERIALIZABLE的乐观锁定,它跟踪事务间的依赖关系,如果检测到循环依赖关系则中止。这不遵循锁的语义,并且明确地做起来不会非常有用。