6

我对 Oracle 阻塞有点了解——更新如何阻塞其他更新直到事务完成,作者如何不阻塞读者等。

我了解悲观和乐观锁定的概念,以及有关丢失丢失更新等的典型银行教科书示例。

我也了解 JDBC 事务隔离级别,例如,我们很高兴看到未提交的数据。

然而,我对这些概念如何相关和相互作用有点模糊。例如:

  • Oracle 是否默认提供悲观或乐观锁定(它似乎只是阻止了基于两个 TOAD 会话中的实验的单独更新。)
  • 如果我怀疑这些是应用程序级别的概念,那么当我可以让数据库同步事务更新时,我为什么还要麻烦实施锁定策略呢?
  • 当我的应用程序以外的其他客户端以不同的隔离级别访问时,事务隔离级别(我在连接上设置)如何改变数据库行为。

任何澄清这些主题的词将不胜感激!

4

3 回答 3

3
  • Oracle 允许使用任何一种类型的锁定 - 您构建应用程序的方式决定了使用什么。回想起来,这并不是一个真正的数据库决定。

  • 大多数情况下,Oracle 的锁定在与数据库的有状态连接中就足够了。在无状态应用程序中,例如 Web 应用程序,您不能使用它。在这种情况下,您必须使用应用程序级锁定,因为锁定适用于会话。

  • 通常你不需要担心它。在 Oracle 中,读取器从不阻塞写入器,写入器从不阻塞读取器。Oracle 的行为不会随着各种 ANSI 隔离级别而改变。例如,Oracle 中没有“脏读”之类的东西。Tom Kyte 指出,允许脏读的精神是避免阻塞读,这在 Oracle 中不是问题。

我强烈推荐阅读 Tom Kyte 的优秀著作“专家 Oracle 数据库架构”,其中非常清楚地解决了这些和其他主题。

于 2010-08-06T18:16:17.090 回答
2

乐观锁基本上是“我只会在修改数据时锁定数据,而不是在读取数据时锁定”。问题是,如果您不立即锁定数据,其他人可以在您这样做之前更改它并且您正在查看旧新闻(并且可以盲目地覆盖在您读取数据和更新数据之间发生的更改。 )

悲观锁定是在您读取数据时锁定数据,以便在您决定更新数据时确保没有人更改它。

这是一个应用程序决策,而不是 Oracle 决策,因为:

从表 1 中选择 x、y、z,其中 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

于 2010-08-06T18:23:22.607 回答
1

Oracle 总是处理悲观锁定。也就是说,它会在更新时锁定一条记录(如果涉及到密钥,您也可以锁定删除和插入)。您可以使用 SELECT....FOR UPDATE 来增加悲观锁定策略。

实际上,任何以事务方式工作的数据库/存储引擎都必须执行某种形式的锁定。

SERIALIZABLE 隔离级别更接近于乐观锁定机制。如果事务尝试更新自事务开始以来已更新的记录,它将引发异常。但是,它依赖于数据库会话和最终用户会话之间的一对一关系。

随着连接池/无状态应用程序变得普遍,特别是在用户活动繁重的系统中,长时间绑定数据库会话可能是一个糟糕的策略。乐观锁定是首选,更高版本的 Oracle 通过 ORA_ROWSCN 和 ROWDEPENDENCIES 项支持此功能。基本上,它们使您更容易查看自您最初/上次查看记录以来是否已更改记录。

由于数据库会话和用户会话之间的一对一关系已经成为传统,应用程序层保留了更多的“用户会话”状态,因此更有责任检查用户做出的五/十选择几分钟前仍然有效(例如,这本书还在存货中,还是其他人购买了它)。

于 2010-08-07T01:13:58.087 回答