MyBatis-Puls的insertBatch提示出现Dead Lock问题

1,605 阅读1分钟

先说场景:使用了事务(配置默认),事务中是使用了insertBatch方法进行批量插入,批量插入前,进行了批量删除的操作,并且是多线程,数据量很大!表中数据量也很大!

org.springframework.dao.DeadlockLoserDataAccessException: com.xxxMapper.insert (batch index #1) failed. Cause: java.sql.BatchUpdateException: Deadlock found when trying to get lock; try restarting transaction  
; Deadlock found when trying to get lock; try restarting transaction; nested exception is java.sql.BatchUpdateException: Deadlock found when trying to get lock; try restarting transaction

那么就是看日志突然出现了死锁,考虑了数据量大的问题,还是多线程,就怀疑是删除和插入冲突了,查了查, 在repeatable(即默认隔离级别)级别,在操作是会持有X(互斥锁)gap锁(间隙锁)的,

来,解决方案:

第一种方案:将事务隔离级别降低到read committed即可,此时无gap锁,T-A、T-B无冲突。

第二种方案:事务隔离级别仍然为repeatable read,但将参数innodb_locks_unsafe_for_binlog置为true。

这里我就是采用了第一种方案解决的,直接Spring事务注解如下:

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

当然我是手动获取事务,是这样写

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
// 设置隔离级别为SERIALIZABLE
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
TransactionStatus status = transactionManager.getTransaction(def);

感谢:

多线程更新/插入同一表出现数据库死锁(Dead Lock)问题解决