维护跨事务的更新顺序以避免死锁 [英] Maintaining order of updates across transactions to avoid deadlocks

查看:48
本文介绍了维护跨事务的更新顺序以避免死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

nhibernate 是否有某种方式来维护更新顺序以避免并发事务之间的死锁?

Does nhibernate have some way of maintaining order of updates to avoid deadlocks across concurrent transactions?

例如,如果我有两个事务 T1 和 T2 同时执行.假设我要更新名为 order 的表中名为 cancelled 的字段中的 2 行.

For example if I have two transactions T1 and T2 executing concurrently. Let's say I'm updating 2 rows in a table called order on a field called cancelled.

T1

Update order set cancelled = 0 where order_id = 1
Update order set cancelled = 0 where order_id = 2

T2

Update order set cancelled = 0 where order_id = 2  
Update order set cancelled = 0 where order_id = 1 

显然,如果它们同时或大约在同一时间执行,上述内容将导致死锁,因为 T1 将等待获取订单 2 上的锁,而 T2 将等待获取订单 1 上的锁.

Obviously the above will result in a deadlock if they both execute at or around the same time because T1 will be waiting to acquire a lock on order 2 and T2 will be waiting to acquire a lock on order 1.

我的问题是如何确保这些更新的顺序始终相同?这是否只是通过在两个事务中以相同的顺序更新实体来处理?

My question is how do I ensure that the order of these updates are always the same? Is this simply handled by updating the entities in the same order in both transactions?

因此,如果我对实体执行以下操作,我是否可以保证更新会以正确的顺序发生?

So if I do the following on the entities am I guaranteed the updates will occur in the right order?

Order order1 = session.Get<Order>(1);
Order order2 = session.Get<Order>(2);

using(ITransaction tran = session.StartTransaction())
{
    order1.Cancelled = 0;
    order2.Cancelled = 0;
    tran.Commit();
}

除此之外,我想知道跨不同表的更新.因此,如果我要更新一个名为 order 的表和一个名为 order_line 的表,类似于上面的示例,nhibernate 是否有某种自动方式每次都以相同的顺序执行此操作?

In addition to this I wonder about updates across different tables. So if I were to update a table called order and also a table called order_line similar to the example above does nhibernate have some automagical way of doing it in the same order every time?

从 v4 开始,实体框架似乎确实支持这一点.以下文章对此进行了解释:

It appears the entity framework does support this natively as of v4. The below article explains this:

操作顺序
EF 没有公开控制SaveChanges 期间的操作顺序.EF v1 确实有特定的高隔离级别(例如可序列化)的问题,这可能在 SaveChanges 期间产生死锁.这不是一个很好的宣传功能,但在 EF 4 中我们更改了更新管道以使用更多不相关 CUD 操作的确定性排序.这有助于确保一个程序的多个实例将使用相同的顺序在更新同一组表时,这反过来有助于减少可能出现死锁.

Ordering of operations
EF does not expose a way to control the ordering of operations during SaveChanges. EF v1 indeed had specific issues with high isolation levels (e.g. Serializable) which could produce deadlocks during SaveChanges. It is not a very well publicized feature, but in EF 4 we changed the update pipeline to use more deterministic ordering for uncorrelated CUD operations. This helps ensure that multiple instances of a program will use the same ordering when updating the same set of tables, which in turns helps reduce the possibility of a deadlock.

除了SaveChanges,如果你需要有高在执行查询时进行隔离,您可以手动实现类似的方法:确保您的应用程序始终访问相同的一对相同顺序的表,例如使用字母顺序.

Besides SaveChanges, if you need to have transactions with high isolation while executing queries, you can manually implement a similar approach: make sure your application always accesses the same pair of tables in the same order, e.g. use alphabetical order.

以上摘自 这里

显然,从 2013 年 1 月开始,nhusers 组中也有一个帖子:https://groups.google.com/forum/#!searchin/nhusers/deadlock/nhusers/WVCEJfD3B_w/DGBhHta79cMJ

Apparently there is also a post in the nhusers group on this from January of 2013: https://groups.google.com/forum/#!searchin/nhusers/deadlock/nhusers/WVCEJfD3B_w/DGBhHta79cMJ

推荐答案

我想我通过挖掘 nhibernate 代码找到了答案.答案是肯定的和否定的.NHibernate 确实能够对 INSERT 语句进行排序,但您必须通过以下方式在配置文件中手动设置此配置:

I think I found my answer by digging through the nhibernate code. The answer is yes and no. NHibernate does have the ability to order the INSERT statements but you have to manually set this configuration in the config file via:

<property name="order_inserts">true</property>

这里要注意的一件有趣的事情是,如果 adonet.batch_size > 0,它将默认为 true.如果这不是 > 0,您需要手动设置.

One interesting thing to note here is that it will default to true if adonet.batch_size is > 0. If this is not > 0 you need to manually set this.

NHibernate 中的更新没有同样的功能.底层类支持这一点,但他们无法从配置文件中设置它,并且默认值(C# 中的默认布尔值)为 false.如果他们将其暴露给配置,则会订购在刷新命令或事务中执行的更新.

Updates in NHibernate do NOT have this same functionality. The underlying classes support this but they do not have a way to set it from the config file and the default value (default boolean value in C#) is false. Should they ever expose this to the configuration the updates executed in a flush command or transaction would be ordered.

NHibernate 对 INSERTS 排序的方式是按类名然后按主键.如果他们公开更新顺序,它将以相同的方式工作.我希望有人觉得这很有见地,因为我确实做到了.

The way NHibernate orders the INSERTS is by class name then by primary key. Should they ever expose the update ordering it would work the same way. I hope someone finds this insightful because I sure did.

如果有人对支持此功能的底层类感兴趣,则是 Settings.这是一个名为:

If anyone is interested the underlying class that supports this is Settings. It's a property called:

public bool IsOrderUpdatesEnabled { get; internal set; }

这篇关于维护跨事务的更新顺序以避免死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆