mysql lock wait t_Mysql lock wait timeout

前段时间遇到一个问题,有个事务内的代码,但是显然没有全部回滚,导致业务事务不完整;error message如下

org.springframework.dao.CannotAcquireLockException:

### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

如上显示,遇到的MySQLTransactionRollbackException,触发原因是“锁等待超时”,从mysql connector中抛出,抛出位置的代码如下,可以看到

#SQLError.class

public static SQLException createSQLException(String message, String sqlState, int vendorErrorCode, boolean isTransient, Throwable cause,

ExceptionInterceptor interceptor) {

try {

SQLException sqlEx = null;

if (sqlState != null) {

if (sqlState.startsWith("08")) {

if (isTransient) {

sqlEx = new SQLTransientConnectionException(message, sqlState, vendorErrorCode);

} else {

sqlEx = new SQLNonTransientConnectionException(message, sqlState, vendorErrorCode);

}

} else if (sqlState.startsWith("22")) {

sqlEx = new SQLDataException(message, sqlState, vendorErrorCode);

} else if (sqlState.startsWith("23")) {

sqlEx = new SQLIntegrityConstraintViolationException(message, sqlState, vendorErrorCode);

} else if (sqlState.startsWith("42")) {

sqlEx = new SQLSyntaxErrorException(message, sqlState, vendorErrorCode);

//40开头的sqlstate都会抛出这个异常

} else if (sqlState.startsWith("40")) {

sqlEx = new MySQLTransactionRollbackException(message, sqlState, vendorErrorCode);

} else if (sqlState.startsWith("70100")) {

sqlEx = new MySQLQueryInterruptedException(message, sqlState, vendorErrorCode);

} else {

sqlEx = new SQLException(message, sqlState, vendorErrorCode);

}

} else {

sqlEx = new SQLException(message, sqlState, vendorErrorCode);

}

if (cause != null) {

try {

sqlEx.initCause(cause);

} catch (Throwable t) {

// we're not going to muck with that here, since it's an error condition anyway!

}

}

return runThroughExceptionInterceptor(interceptor, sqlEx);

} catch (Exception sqlEx) {

SQLException unexpectedEx = new SQLException(

"Unable to create correct SQLException class instance, error class/codes may be incorrect. Reason: " + Util.stackTraceToString(sqlEx),

MysqlErrorNumbers.SQL_STATE_GENERAL_ERROR);

return runThroughExceptionInterceptor(interceptor, unexpectedEx);

}

}

到这里有几个疑问,1.什么情况下会造成lock wait timeout?2.为什么lock timeout为什么事务不全部回滚?3.为什么这里的异常命名用MySQLTransactionRollbackException?

1.什么情况下会造成lock wait timeout?

在mysql官网可以看得到关于lock wait timeout相关的配置如下,由于一行数据被另一个事务锁定,导致当下的事务一直等待,直至超时!(当然锁等待超时一般是不太容易的,要么是超时时间设置的太短,要么是代码逻辑上出现了死锁)

33ab13d517f562a1a347eae7c758dde4.png

2.为什么lock timeout为什么事务不全部回滚?

继续往下看,可以知道mysql服务队锁等待超时的情况,不会回滚整个事务,如果需要锁等待超时回滚整个事务,需要配置参数innodb_rollback_on_timeout为true;(事实上现在的持久层框架,在遇到异常时,可以做到帮我们回滚整个事务,如spring的@Transactional注解)

b13ddb779d02c1d55a61978154179a17.png

3.为什么这里的异常命名用MySQLTransactionRollbackException?

我当初第一次看这个异常的名字,第一感觉是事务回滚过程中产生的异常,事实上,并不是。我翻阅相关文档,并没有任何解释,而且代码上也没有相关的注释,暂时只能不管他了!

Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值