项目使用技术SpringBoot+MyBatis+Oracle
来自生产血淋淋的教训,请大家引以为戒
需求分析
有100w数据,需要通过接口导入数据库,数据库使用的oracle。
为了能够保证数据顺利的插入,进行了分批,并且,使用了编程式事务进行提交。
实现代码如下:
//如果自动提交设置为true,将无法控制提交的条数,改为最后统一提交,可能导致内存溢出
SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
//不自动提交
try {
List<User> lists = new ArrayList<>();
UserDao userDao = session.getMapper(UserDao.class);
for (int i = 0; i < list.size(); i++) {
lists.get(i)
if(i == 0){
continue;
}
if (i % 400 == 0 || i == list.size() - 1) {
userDao.bacthUpdate(lists);
//手动每400条提交一次,提交后无法回滚
session.commit();
//清理缓存,防止溢出
session.clearCache();
lists = new ArrayList<>();
}
}
} catch (Exception e) {
//没有提交的数据可以回滚
session.rollback();
} finally {
session.close();
}
- 乍一看没有什么问题,最后一批也是顺利提交了。但是执行两次就把数据库锁定了两次。
起因
测试的时候是一条数据,执行了两次。当一条数据传入的时候,事务被开启,但是if判断直接将执行的这条数据跳出来了循环,并没有能够直接提交。
事务开启,不提交直接关闭
解决办法
if(list.size() != 1 && i == 0){
continue;
}