nhibernate是否有某种方法来维护更新顺序以避免并发事务中的死锁?
例如,如果我有两个事务T1和T2并发执行。我们假设我在一个名为ordered的表中更新了2行,这个名称取消了。
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阶段的锁定。
我的问题是如何确保这些更新的顺序始终相同?这只是通过在两个交易中以相同的顺序更新实体来处理吗?
因此,如果我对实体执行以下操作,我保证更新将以正确的顺序进行吗?
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是否有一些自动化的方式每次以相同的顺序执行它?
从v4开始,实体框架似乎确实支持这种做法。以下文章解释了这一点:
操作顺序
EF没有暴露出一种控制方式 在SaveChanges期间排序操作。 EF v1确实具体 具有高隔离级别(例如Serializable)的问题 在SaveChanges期间产生死锁。这不是一个很好的宣传 功能,但在EF 4中,我们更改了更新管道以使用更多 不相关CUD操作的确定性排序。这有帮助 确保程序的多个实例将使用相同的顺序 当更新同一组表时,这反过来有助于减少 陷入僵局的可能性。除了SaveChanges,如果你需要有高额的交易 执行查询时隔离,可以手动实现 类似的方法:确保您的应用程序始终访问相同的方法 以相同顺序的一对表,例如使用字母顺序。
以上内容取自here
显然,从2013年1月开始,nhusers小组中也有一个帖子: https://groups.google.com/forum/#!searchin/nhusers/deadlock/nhusers/WVCEJfD3B_w/DGBhHta79cMJ
答案 0 :(得分:2)
我想我通过挖掘nhibernate代码找到了答案。答案是肯定的,不是。 NHibernate确实能够订购INSERT语句,但您必须通过以下方式在配置文件中手动设置此配置:
<property name="order_inserts">true</property>
这里要注意的一件有趣的事情是,如果adonet.batch_size
是&gt;它将默认为true。 0.如果不是> 0你需要手动设置它。
NHibernate中的更新没有相同的功能。底层类支持这一点,但它们没有办法从配置文件中设置它,默认值(C#中的默认布尔值)为false。如果他们将此暴露给配置,则将对订单中的执行更新进行排序。
NHibernate命令INSERTS的方式是按类名,然后是主键。如果他们公开更新订单,它将以相同的方式工作。我希望有人能发现这一点很有见地,因为我确实这样做了。
如果有人感兴趣,支持此功能的基础类是Settings
。这是一个名为:
public bool IsOrderUpdatesEnabled { get; internal set; }