我使用Hibernate和联合子类将类层次结构映射到数据库。不幸的是,当一个对象被更新时,当一个不同的线程试图加载同一个对象时,这会导致死锁。对于映射到单个表的对象,这是没有问题的。这似乎是由MSSQL获取类层次结构表上的锁的方式造成的。
当Hibernate从数据库加载对象时,它使用带有联接的SELECT:
SELECT ...
FROM
subclass
LEFT JOIN class
ON ...
WHERE ...当Hibernate更新这个子类的对象时,它会:
UPDATE
class
SET ...
WHERE ...
UPDATE
subclass
SET ...
WHERE ...问题是,如果在两个update语句之间加载对象,则会导致死锁。SELECT语句似乎一个接一个地锁着两个表。所以似乎发生的是:
死锁图如下所示:死锁图
这些对象经常被更新,并且经常会导致死锁,即使只加载单个对象也是如此。我还试图重现HSQLDB的问题,但是它没有死锁,HSQLDB似乎要么同时锁定两个表,要么等待直到能够同时锁定两个表,因此它似乎是一个仅在MSSQL中发生的问题。
在不修改模式(索引除外)的情况下,如何避免Hibernate出现这个问题?
发布于 2010-09-02 16:39:45
你打开Server死锁跟踪标志1204或1222了吗?这将有助于准确地确定导致死锁的资源。有关更多信息,请参见关于检测和终止死锁的MSDN文章。
这些表上有索引吗?如果是这样的话,如果应用程序获得聚集索引上的锁,则可能会发生死锁,然后通过查找非聚集索引尝试在同一表上获取更多锁。
发布于 2010-09-02 12:32:54
在我看来,这些更新需要在单个事务中原子地完成。不幸的是,我没有太多关于Hibernate的背景知识,所以我将把它留给其他人去指出正确的方向。
https://stackoverflow.com/questions/3627036
复制相似问题