我们在开发中,有时候需要手动开启事务,千万要记得,事务开启了之后,要么commit,要么rollback,如果在中间环节跳过,那么其他业务也要申请这个表的事务锁的时候,它们只有等待锁超时之后才是能获取到锁,于是就出现如下异常:
org.springframework.dao.CannotAcquireLockException: PreparedStatementCallback; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction......
我以Magic-Api的SQLModule操作来举个例子。
1、错误的使用方式
@Component
@RequiredArgsConstructor
public class TxDemo {
private final SQLModule db;
public void doSomething() {
Transaction tx = db.transaction();
try {
// 直接return出去,或者在try外层有for循环的时候continue,都会导致tx没有提交事务,只有等待超时,这时候其他业务在竞争事务锁的时候都是处于等待状态,那就会导致出现主题的错误问题
return;
}catch (Exception e) {
tx.rollback();
}
}
}
2、正确的使用方式
@Component
@RequiredArgsConstructor
public class TxDemo {
private final SQLModule db;
public void doSomething() {
Transaction tx = db.transaction();
try {
// 正常提交事务
tx.commit();
}catch (Exception e) {
tx.rollback();
}
}
}