【发布时间】:2014-02-14 10:45:36
【问题描述】:
我在我的项目中使用休眠,但对于非常简单的数据库操作,我遇到了随机的明显死锁。
有一个堆栈跟踪:https://gist.github.com/knyttl/8999006 - 让我感到困惑的是,第一个异常是 RollbackException,然后是 LockAquisition 异常。
问题经常发生在类似的子句上:
@Transactional
public void setLastActivity() {
User user = em.findById(...);
user.setLastActivity(new Date());
em.merge(user);
em.flush();
}
我很困惑,因为我不知道是 Hibernate、MySQL 还是 C3P0 的问题。
我的休眠配置:
<prop key="hibernate.dialect">${database.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${database.structure}</prop>
<prop key="hibernate.connection.url">${database.connection}</prop>
<prop key="hibernate.connection.username">${database.username}</prop>
<prop key="hibernate.connection.password">${database.password}</prop>
<prop key="hibernate.connection.driver_class">${database.driver}</prop>
<prop key="hibernate.connection.shutdown">true</prop>
<prop key="hibernate.connection.writedelay">0</prop>
<prop key="hibernate.connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
<prop key="hibernate.show_sql">${database.show_sql}</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.ejb.metamodel.generation">disabled</prop>
<!-- Use the C3P0 connection pool provider -->
<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.c3p0.min_size">0</prop>
<prop key="hibernate.c3p0.max_size">50</prop>
<prop key="hibernate.c3p0.timeout">120</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.max_statementsPerConnection">0</prop>
<prop key="hibernate.c3p0.maxStatementsPerConnection">0</prop>
<prop key="hibernate.c3p0.idle_test_period">120</prop>
<prop key="hibernate.c3p0.acquire_increment">1</prop>
<prop key="hibernate.c3p0.numHelperThreads">8</prop>
编辑1:
- 我在上面写道,发生了明显的死锁 - 这是错误的,只有“尝试获取锁时发现死锁”发生。
EDIT2:
这也发生在这些方法上 - 那些需要用 @Transactional 注释的方法:
@Transactional
public void setLastActivity() {
em.insertNative("table")
.values(...)
.execute();
}
【问题讨论】:
-
您需要提供更多详细信息,例如您使用堆栈跟踪获得的实际异常。我的意思是,不是在某些可能被公司防火墙阻止的外部站点上。
-
您可能想要设置 autocommit=false。
-
Gimby:给出了堆栈跟踪 - 仔细看。 brettw:你能提供更多信息吗?为什么会有帮助?
-
当你摆脱@Transactional 时会发生什么?由于 @Transactional 注释,最近与休眠发生了死锁。
-
setLastActivity方法有点奇怪,user是一个附加实体,所以不需要合并,合并对附加实体没有影响。也不需要在方法结束之前刷新,因为 spring 会为我们做刷新。进行手动冲洗有什么特殊原因吗?可能是相关的