【发布时间】:2020-08-30 05:07:17
【问题描述】:
当我从 mysql 得到一个异常时,如下异常
19:36:35,712 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - SQL Error: 1205, SQLState: 40001
19:36:35,713 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - Lock wait timeout exceeded; try restarting transaction
org.springframework.dao.PessimisticLockingFailureException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.PessimisticLockException: could not execute statement
该特定连接处于错误状态,然后 10 分钟后我收到以下错误
19:48:41,859 WARN [com.mchange.v2.c3p0.impl.NewPooledConnection] - [c3p0] A PooledConnection that has already signalled a Connection error is still in use!
19:48:41,859 WARN [com.mchange.v2.c3p0.impl.NewPooledConnection] - [c3p0] Another error has occurred [ java.sql.SQLNonTransientConnectionException: No operations allowed after connection closed. ] which will not be reported to listeners!
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: The last packet successfully received from the server was 716,308 milliseconds ago. The last packet sent successfully to the server was 716,308 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem
通常当发生应用程序级异常时,事务回滚并且连接可用于将来的请求。
Mysql 的例外情况如何实现?
我使用 java spring hibernate mysql 和 c3p0
这是配置
hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
hibernate.hbm2ddl.delimiter=;
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=250
hibernate.c3p0.checkout_timeout=120000
hibernate.c3p0.test_connection_on_checkin=true
hibernate.c3p0.idle_connection_test_period=300
hibernate.archive.autodetection=class
hibernate.hbm2ddl.auto=validate
代码位于@Transactional 函数中
@Override
@Transactional(
rollbackFor = Exception.class)
public Long create() {
//Hibernate and queryDsl code
}
或者有时我必须像这样手动管理事务,因为如果最后一个函数失败,我不想回滚。我相信这是导致问题的功能。
public void function(){
try {
final TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
final TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
try {
//Hibernate and QueryDsl code
entityManager.flush();
platformTransactionManager.commit(transactionStatus);
} catch(Throwable t) {
LOG.error(t);
platformTransactionManager.rollback(transactionStatus);
entityManager.clear();
throw t;
}
// Call a transactional function
transactionFunction();
}
}
编辑
删除了关于重复键错误的部分,因为我现在可以确认它与问题无关。
【问题讨论】:
-
Spring 从 c3p0 迁移到 HikariCp,可以考虑更换连接池吗?
-
尝试清除脚本中的会话。
-
@PeterDarmis 我确实调用了 entitymanager.clear() 但在等待超时异常后连接仍处于不良状态
标签: mysql spring hibernate c3p0