nHibernate锁定 - LockMode UPGRADE在同一行上执行NONE读取之后阻塞

时间:2016-09-01 19:12:27

标签: c# sql-server nhibernate locking race-condition

我们有一个卡片订单流程,可能需要几秒钟才能运行。此过程中的数据使用nHibernate中的LockMode.UPGRADE运行。

在第一个订单流程完成创建竞争条件并且似乎使用原始行数据之前,偶尔会触发带有LockMode.NONE运行的第二个(webhook)进程。它没有被阻止,直到第一个完成,所以获得旧数据。

由于我们的数据库没有使用NO WAIT或任何其他SNAPSHOT COMMITTED设置运行。

我的问题是:lockmode.none可以以某种方式忽略UPGRADE锁并读取旧数据(可能是缓存吗?)

感谢。

1 个答案:

答案 0 :(得分:0)

升级锁是为了防止另一个事务获取相同的数据进行升级。

以读取提交模式运行而没有额外锁定的事务仍然可以读取它们。您需要一个独占锁来阻止读取已提交读取(前提是它们没有快照隔离级别)。详细了解Technet

据我所知,NHibernate没有提供一种在实体读取上发出独占锁的方法。 (您将通过实际更新事务中的实体来获取它们。)您可以使用CreateSQLQuery直接在DB中发出锁来解决此问题。或者在您的webhook过程中,也获得升级锁定。

但是这条道路肯定会导致死锁或锁定争用。

更一般地说,通过调整代码模式来避免显式锁定是优选的。我刚刚编写了一个示例here,请参阅"没有明确的锁定"溶液

至于你的webhook流程,这两种情况之间真的有什么不同吗?

  1. 它获取的数据没有任何更新锁定,但在处理数据之前,订单处理会更新其数据。
  2. 它获取其数据,包括一些对其进行更新锁定的数据。
  3. 通常,您仍然会遇到同样的问题需要解决,并且避免2.将无法解决1.这也是流程处理其数据的方式,需要对其进行调整以支持并发。 (提示:使用长时间运行的事务来解决1.肯定会导致锁争用。)