大多数RDBMS允许在所选行上获取共享锁独占锁。例如,PostgreSQL有这样的语法:
SELECT *
FROM post
WHERE id=10
FOR SHARE;
使用FOR SHARE,即使在READ_COMMITTED隔离级别,我们也可以获取共享锁,并且可以防止不可重复的读取现象,而无需实际使用REPEATABLE_READ事务隔离。
但是为了防止幻像读取,SERIALIZABLE是唯一的方法。为什么没有明确的锁定语法来获取谓词锁?
据我所知,我不记得在Oracle,SQL Server,MySQL或PostgreSQL中看过任何这样的构造。
答案 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
的乐观锁定,它跟踪事务间的依赖关系,如果检测到循环依赖关系则中止。这不遵循锁的语义,并且明确地做起来不会非常有用。