【发布时间】:2016-01-06 13:36:34
【问题描述】:
大多数 RDBMS 允许在被选择的行上获取共享独占锁。例如,PostgreSQL 有这样的语法:
SELECT *
FROM post
WHERE id=10
FOR SHARE;
使用 FOR SHARE,即使在 READ_COMMITTED 隔离级别,我们也可以获取共享锁,并且可以在不实际使用 REPEATABLE_READ 事务隔离的情况下防止不可重复读取现象。
但是为了防止幻读,SERIALIZABLE 是唯一的方法。为什么没有明确的锁定语法来获取谓词锁?
据我所知,我不记得在 Oracle、SQL Server、MySQL 或 PostgreSQL 中看到过任何此类结构。
【问题讨论】:
-
FOR SHARE 获得一个读锁,而 FOR UPDATE 给你一个写锁。使用 SERIALIZABLE 时,数据库会在所有检索到的行上获取 SHARED 锁(以防止模糊读取)以及范围/谓词锁(以防止幻读)。
-
为什么要在每个查询中强制执行事务隔离级别,而不仅仅是使用事务隔离级别?在 Oracle 中,您始终可以对 SCN 使用闪回查询来避免幻读(如果您将事务隔离级别设置为可序列化,这就是 Oracle 在幕后所做的事情)。这不需要任何形式的锁定或任何形式的阻止其他会话。但它与抛出 ORA-08177: Cannot serialize access for this transaction error for non-serializable modify 的行为不同。
-
鉴于您列出的每个数据库可能会有不同的答案,但是,我认为这个问题要么“过于宽泛”,要么“主要基于意见”。
-
隔离级别设置在连接级别,从该特定连接启动的所有事务都将继承它。我想到了一个更细粒度的控制,我可以在较低的隔离级别 (READ_COMMITTED) 上使用显式锁定来防止一些异常
-
它可能被标记为不适合 SO 规则,但我认为原因是普遍的,它与冲突解决检测机制有关。
标签: mysql sql-server oracle postgresql transactions