我正在编写一个 Web 应用程序,其中两个不同的用户可以更新一个事情列表,例如待办事项列表。我已经意识到,乐观锁定机制效果最好,因为我不期望高争用。
我正在查看事务隔离级别,现在我有点困惑。看起来不同的事务隔离级别也解决了类似的问题。
这两个不同的概念如何相互关联?如果可能的话,举一个简单的例子。
我正在编写一个 Web 应用程序,其中两个不同的用户可以更新一个事情列表,例如待办事项列表。我已经意识到,乐观锁定机制效果最好,因为我不期望高争用。
我正在查看事务隔离级别,现在我有点困惑。看起来不同的事务隔离级别也解决了类似的问题。
这两个不同的概念如何相互关联?如果可能的话,举一个简单的例子。
这两件事都与数据一致性和并发访问有关,但它们是两种不同的机制。
锁定可防止对某些对象的并发访问。例如,当您尝试更新待办事项列表项时,使用悲观锁定数据库会在记录上放置行锁,直到您提交或回滚事务,这样就不允许其他事务更新同一记录。乐观锁定是应用程序端检查记录的时间戳/版本在获取和尝试更新之间是否发生了变化。这与事务隔离级别无关。
事务隔离是关于读一致性。
看看下面的例子,我指出了事务隔离级别之间不同的查询结果。
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 指定的事务隔离级别(上例中没有提到的一个是“可重复读取”),除了可序列化之外,所有这些都受到一些异常的影响。请注意,它与锁定无关。
您可以在此处查看有关此的 Oracle 文档,这些概念非常普遍。
最后,您使用乐观锁定的方法对于 Web 应用程序似乎是明智的。很可能您获取一个列表项并在两个不同的 HTTP 请求中更新它。在获取之后通过显式锁定记录来保持事务打开是不可能的(或者至少是不明智的)(你怎么知道第二个请求是否会到达?)乐观锁定可以优雅地处理这个问题。
锁定机制通常用于实现事务隔离级别。因此,事务隔离级别定义了您的事务在并发执行中的行为方式。锁定机制是实现细节。
从应用程序编写的角度来看,您应该专注于设置适当的事务隔离级别。当然,设置特定的隔离级别意味着锁定,但只要您的应用程序没有处于高负载下,您就不需要过多关注它。
重要的是数据库引擎之间的锁定机制不同。如果您为一个数据库编写应用程序并在一段时间后更改数据库引擎,您的应用程序可能会表现不同,或者其中的某些部分可能需要重写。
我从 15 年的业务应用程序开发中得出的建议是不要依赖显式锁定。