锁定机制(悲观/乐观)与数据库事务隔离级别有何关系?

时间:2014-03-25 21:05:34

标签: database concurrency isolation-level optimistic-locking pessimistic-locking

我正在编写一个Web应用程序,例如,两个不同的用户可以更新列表中的事情列表。我已经意识到,乐观锁定机制最有效,因为我不期望高争用。

我正在查看事务隔离级别,现在我有点困惑。看起来不同的事务隔离级别也解决了类似的问题。

这两个不同的概念如何相互关联?如果可能的话,举个简单的例子。

2 个答案:

答案 0 :(得分:17)

这两件事都与数据一致性和并发访问有关,但它们是两种不同的机制。

锁定会阻止并发访问到某个对象。例如,当您尝试更新待办事项列表项时,使用悲观锁定数据库会在记录上放置行锁,直到您提交或回滚事务为止,这样就不允许其他事务更新同一记录。乐观锁定是应用程序端检查记录的时间戳/版本是否在获取和尝试更新之间发生了变化。这与事务隔离级别无关。

交易隔离与读取一致性有关。

  • 读取未提交级别允许会话查看其他会话的未提交更改
  • 读取已提交级别允许会话仅查看其他会话的已提交更改
  • 可序列化级别允许会话仅查看在事务开始之前提交的更改

看一下下面的例子,我指出了事务隔离级别之间不同的查询结果。

SESSION 1                                  SESSION 2
--------------------------------           --------------------------------------
SELECT count(*) FROM test;
=> 10
                                           INSERT INTO test VALUES ('x');

SELECT count(*) FROM test;
=> 10 with read committed/serializable
=> 11 with read uncommited (dirty read)
                                           COMMIT;

SELECT count(*) FROM test;
=> 10 with serializable
=> 11 with read uncommitted/read committed

有四个ANSI指定的事务隔离级别(上面的示例中没有提到的是"可重复读取"),除序列化之外的所有这些都是一些异常的主题。请注意,它与锁定无关。

您可以查看有关此here的Oracle文档,这些概念非常普遍。

最后,您使用乐观锁定的方法对于Web应用程序似乎是明智的。最有可能的是,您获取一个列表项并在两个不同的HTTP请求中更新它。在获取之后保持事务打开并且记录上的显式锁定是不可能的(或者至少是不明智的)(你怎么知道第二个请求是否会到达?)乐观锁定处理这个优雅。

答案 1 :(得分:0)

锁定机制通常用于实现事务隔离级别。因此,事务隔离级别定义了事务在并发执行中的行为方式。锁定机制是实现细节。

从应用程序编写角度来看,您应该专注于设置适当的事务隔离级别。当然,设置特定的隔离级别意味着锁定,但只要您不在重载下使用您的应用程序,您就不需要那么多地处理它。

导入的是数据库引擎之间的锁定机制不同。如果您为一个数据库编写应用程序,并且在一段时间后您将更改数据库引擎,您的应用程序可能会有不同的行为,或者某些部分可能需要重写。

我对业务应用程序开发十五年的建议不是依赖显式锁定。