阻塞、锁定和隔离级别之间有什么关系?

6
我了解一些有关Oracle阻塞的信息——即更新操作会阻塞其他更新操作,直到事务完成;写入者不会阻塞读取等。
我理解悲观锁和乐观锁的概念,并且知道典型的银行教科书中有关失去更新等问题的例子。
我也了解JDBC事务隔离级别,例如我们可以接受看到未提交的数据。
但是我对这些概念如何相关和交互有点模糊。例如:
  • Oracle默认提供悲观锁还是乐观锁(根据在两个TOAD会话中进行实验而得出的结果,它似乎只是阻止了单独的更新操作)。
  • 如果我猜测正确,这些是应用程序级别的概念,那么为什么我要费力地实现锁定策略,当我可以让数据库同步事务更新?
  • 当除我的应用程序以外的其他客户端使用不同的隔离级别时,事务隔离级别(我在连接上设置的)如何改变数据库的行为?
请帮忙澄清这些话题,谢谢!

你的一些问题(特别是关于不同客户端之间的影响)可能会在这里得到解答:http://en.wikipedia.org/wiki/Isolation_%28database_systems%29 - user166390
3个回答

3
  • Oracle支持两种类型的锁定方式——你应用程序的构建方式决定了使用哪种。回顾一下,这实际上不是一个数据库决策。

  • 通常情况下,在与数据库进行有状态连接时,Oracle的锁定已经足够了。在非有状态应用程序中,例如Web应用程序,您不能使用它。在这种情况下,您必须使用应用程序级别的锁定,因为锁定适用于会话。

  • 通常情况下,您不需要担心它。在Oracle中,读者从不阻止写者,而写者也从不阻止读者。 Oracle的行为不随各种ANSI隔离级别而改变。例如,在Oracle中不存在“脏读”之类的问题。 Tom Kyte指出,允许脏读取的精神是为了避免阻塞读取,这在Oracle中并不是问题。

我强烈推荐阅读Tom Kyte的优秀著作“Expert Oracle Database Architecture”,其中这些和其他主题都得到了清晰明确地解释。


Oracle确实具有一些不同的隔离级别,其行为也不同。例如,串行化可能会在提交时导致“无法串行化事务”错误,而这种错误在普通隔离级别下是看不到的。 - Shannon Severance
这是我所知道的唯一例外,而且它并不常用。如果您需要使用它,则需要注意这一点。Oracle的多版本实现会处理其他ANSI隔离级别。 - DCookie

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


1

Oracle始终处理悲观锁定。也就是说,当记录被更新时,它将锁定该记录(如果涉及到键,则还可以进行删除和插入锁定)。您可以使用SELECT....FOR UPDATE来增强悲观锁定策略。

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

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

随着连接池/无状态应用程序变得普遍,特别是在具有大量用户活动的系统中,长时间占用数据库会话可能是一种不良策略。优先使用乐观锁定,并且Oracle的后续版本支持ORA_ROWSCN和ROWDEPENDENCIES项目来实现此目的。基本上,它们使查看记录是否自初始/上次查看以来已更改变得更加容易。

随着数据库会话和用户会话之间的一对一关系成为传统,应用程序层保留了更多的“用户会话”状态,因此更负责检查用户五/十分钟前所做的选择是否仍然有效(例如,书籍是否仍有库存,或者其他人是否已经购买了它)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接