我对Oracle阻塞有一点了解 - 在事务完成之前,更新如何阻止其他更新,编写者如何阻止读者等。
我理解悲观和优化锁定的概念,以及关于丢失丢失更新等的典型银行教科书示例。
我也理解JDBC事务隔离级别,例如,我们很高兴看到未提交的数据。
然而,我对这些概念如何相关和相互作用有点模糊。例如:
任何澄清这些主题的词语都会非常感激!
答案 0 :(得分:3)
Oracle允许任何类型的锁定 - 您构建应用程序的方式决定了所使用的内容。回想起来,这不是一个真正的数据库决策。
大多数情况下,Oracle的锁定在与数据库的有状态连接中已足够。在非有状态的应用中,例如网络应用,您无法使用它。在这种情况下,您必须使用应用程序级锁定,因为锁定适用于会话。
通常你不用担心它。在Oracle中,读者永远不会阻止作者,作家也永远不会阻止读者。 Oracle的行为不会随着各种ANSI隔离级别而改变。例如,Oracle中没有“脏读”这样的东西。 Tom Kyte指出允许脏读的精神是避免阻塞读取,这在Oracle中不是问题。
我强烈建议阅读Tom Kyte的优秀书籍“专家Oracle数据库架构”,其中非常清楚地阐述了这些和其他主题。
答案 1 :(得分:2)
乐观锁定基本上是“我只会在修改数据时锁定数据,而不是在我读取数据时”。问题是,如果你不立即锁定数据,其他人可以在你做之前改变它并且你正在查看旧的新闻(并且可以盲目地覆盖在你读取数据和更新数据之间发生的变化。 )
悲观锁定是在您阅读时锁定数据,以便在您决定更新数据时确保没有人更改过数据。
这是一个应用程序决策,而不是Oracle的决定:
SELECT x,y,z FROM table1 WHERE a = 2
不会锁定匹配的记录,但
SELECT x,y,z FROM table1 WHERE a = 2 FOR UPDATE
意愿。所以你必须决定你是否对乐观锁定
SELECT x, y, z FROM table1 WHERE a = 2
...时间过去......
UPDATE table1
SET x = 1, y = 2, z = 3
WHERE a = 2
(你可能已经覆盖了其他人在此期间做出的改变)
或者需要悲观:
SELECT x, y, z FROM table1 WHERE a = 2 FOR UPDATE
...时间过去......
UPDATE table1
SET x = 1, y = 2, z = 3
WHERE a = 2
(您确定自查询以来没有人更改过数据。)
在此处查看Oracle中可用的隔离级别。 http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/consist.htm#CNCPT621
答案 2 :(得分:1)
Oracle ALWAYS处理悲观锁定。也就是说,它会在更新时锁定记录(如果涉及到密钥,您还可以锁定删除和插入的锁)。您可以使用SELECT .... FOR UPDATE来增强悲观锁定策略。
任何以事务方式工作的数据库/存储引擎都必须采取某种形式的锁定。
SERIALIZABLE隔离级别更接近乐观锁定机制。如果事务尝试更新自事务开始以来已更新的记录,它将引发异常。但是,它依赖于数据库会话和最终用户会话之间的一对一。
随着连接池/无状态应用程序变得普遍,特别是在用户活动量很大的系统中,将数据库会话捆绑在较长时间内可能是一个糟糕的策略。优先考虑乐观锁定,后来的Oracle版本通过ORA_ROWSCN和ROWDEPENDENCIES项支持此功能。基本上,它们可以让您更容易看到自最初/最后一次查看以来记录是否已更改。
由于数据库会话和用户会话之间的一对一关系已成为遗留问题,因此应用程序层保留了更多的“用户会话”状态,因此更加负责检查用户所做的选择五/十分钟前仍然有效(例如,该书仍有库存,或其他人是否购买)。