目录
需求
同步A系统多张表(oracle数据库)中的明细数据,插入到本系统的数据库中(MySQL),并做一些汇总计算,最后展示成报表。
第一版:
1.1 方案:
使用一个大事务,覆盖面是所有的同步和汇总计算逻辑。如果程序出错或异常,则事务回滚。
直接按顺序查询A系统的每张表中的所有数据,按条插入B系统指定表中。
1.2 伪代码实现:
interface Service{
void syncAndSummaryData();
}
class ServiceImpl{
@Override
@Transactional(rollbackFor = Exception.class)
public void syncAndSummaryData(){
syncTable1();
syncTable2();
syncTable3();
summaryData();
}
public void syncTable1(){
1、查询A系统的Oracle库table1表中所有数据到ArrayList中
2、for循环逐条插入到本系统的MySQL库中
}
public void syncTable2(){
1、查询A系统的Oracle库table2表中所有数据到ArrayList中
2、for循环逐条插入到本系统的MySQL库中
}
public void syncTable3(){
1、查询A系统的Oracle库table3表中所有数据到ArrayList中
2、for循环逐条插入到本系统的MySQL库中
}
public void summaryData(){
1、将本系统中同步的数据使用SQL的group by分类汇总后,放入ArrayList中
2、for循环逐条插入到本系统中
}
}
1.3 第一版问题:
1、现有的事务机制不支持多个数据库操作,所以方法中事务其实是失效的。
2、存在JVM内存溢出的风险。原因:B系统的JVM最大堆内存是4G,如果A系统中存在一张表中数据量在几百万条(每条数据有45个左右字段),一次性查询出全部数据放入List中,则所有数据全部存放在JVM的堆内存中,可能会撑爆JVM内存。
第二版:
2.1 方案:
1、原有事务不变保持。
2、查询A系统的oracle数据库每张表的逻辑,单独抽成另一个方法,方法上方的事务注解中添加传播机制控制,使用NOT_SUPPORTED,即在查询Oracle数据库方法中挂起当前事务,插入MySQL数据库方法中事务才生效,经过运行测试证明,这样可以起到所有插入操作还是在同一个事务中的效果。
3、查询数据采用分页查询,每次查询1万条。
2.2 伪代码实现:
interface Service{
void syncAndSummaryData();
}
class Servic