首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用MSSQL的Hibernate连接子类死锁

使用MSSQL的Hibernate连接子类死锁
EN

Stack Overflow用户
提问于 2010-09-02 12:24:56
回答 2查看 1.9K关注 0票数 3

我使用Hibernate和联合子类将类层次结构映射到数据库。不幸的是,当一个对象被更新时,当一个不同的线程试图加载同一个对象时,这会导致死锁。对于映射到单个表的对象,这是没有问题的。这似乎是由MSSQL获取类层次结构表上的锁的方式造成的。

当Hibernate从数据库加载对象时,它使用带有联接的SELECT:

代码语言:javascript
复制
SELECT ...
FROM
    subclass
    LEFT JOIN class
        ON ...
WHERE ...

当Hibernate更新这个子类的对象时,它会:

代码语言:javascript
复制
UPDATE
    class
SET ...
WHERE ...

UPDATE
    subclass
SET ...
WHERE ...

问题是,如果在两个update语句之间加载对象,则会导致死锁。SELECT语句似乎一个接一个地锁着两个表。所以似乎发生的是:

  1. 线程1加载一个对象并在两个表上放置共享锁。
  2. 线程1执行类表的UPDATE语句,并将类表上的锁升级为独占锁。
  3. 线程2试图通过执行SELECT语句加载同一个对象,它在子类表上放置一个共享锁,然后等待直到释放类表上的独占锁为止。
  4. 线程1执行子类表的UPDATE语句,它希望将子类表上的锁升级为独占锁,但是该表已经被线程2锁定,该线程正在等待线程1
  5. 由于线程1的死锁,线程2被中止。

死锁图如下所示:死锁图

这些对象经常被更新,并且经常会导致死锁,即使只加载单个对象也是如此。我还试图重现HSQLDB的问题,但是它没有死锁,HSQLDB似乎要么同时锁定两个表,要么等待直到能够同时锁定两个表,因此它似乎是一个仅在MSSQL中发生的问题。

在不修改模式(索引除外)的情况下,如何避免Hibernate出现这个问题?

EN

回答 2

Stack Overflow用户

发布于 2010-09-02 16:39:45

你打开Server死锁跟踪标志1204或1222了吗?这将有助于准确地确定导致死锁的资源。有关更多信息,请参见关于检测和终止死锁的MSDN文章。

这些表上有索引吗?如果是这样的话,如果应用程序获得聚集索引上的锁,则可能会发生死锁,然后通过查找非聚集索引尝试在同一表上获取更多锁。

票数 1
EN

Stack Overflow用户

发布于 2010-09-02 12:32:54

在我看来,这些更新需要在单个事务中原子地完成。不幸的是,我没有太多关于Hibernate的背景知识,所以我将把它留给其他人去指出正确的方向。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3627036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档