需求:
有一个表叫目标表,这里存了对应每个员工个日、周和月目标。这个表里面的字段大致分为4类,每一类记录不同方面的业绩,例如a记录订单,b记录销售,然后每一类有一个目标数量和真实数量。现在需要每天晚上12点之后都重新计算一下所有员工的昨日目标和最近的周、月目标完成的真实数量,表结构大致是下面这个样子。
出现的问题:
现在的实现方式是写了4个定时任务,比如methodA、methodB、methodC和methodD来分别计算不同的目标,我是先获得了所有的员工的集合,然后放到for循环里面,单独查出每个员工的对应的那条目标数据,重点在于有的员工可能没有给自己创建目标,这个时候我就要给他创建一条目标数据,只填写真实数量,目标数量就空着,如果他自己已经创建了我就直接更新这条数据里对应的数量字段,代码逻辑大概是这样的。
public void methodA(){
//查询所有员工的id
List<Integer> userIds = userService.findList(queryVo);
for(Integer userId:userIds){
//查询每个老师的目标数据
GoalsVo goalsVo = new GoalsVo();
goalsVo.setUserId(userId);
if (goalsVo!=null){
//更新
}else{
//新增一条数据
}
}
问题就在于因为因为是分成4个方法去更新同一个员工的不同的数据,如果当methodA没有查到目标数据,走到了新增数据的逻辑里面时但是还没执行插入的时候,刚好methodB也查到这个员工没有目标数据,也走到了新增数据的逻辑里面,这样的话就会造成一个员工有两条目标记录数据。
解决思路:
现在想到了一些思路但是感觉还是有问题。
1.再写一个定时任务,专门检查有没有创建目标数据,但是数据多了话,也可能造成那个上述结果
2.将每个定时任务之间的时间拉长一点,错开,治标不治本。
3.设置索引,避免一个员工同一天有多个日目标数据,但是这样的话后面执行的方法里面的数据就没办法更新到前面先创建的数据里,造成数据丢失
请问有什么好的解决方法吗?
=======================================
非常感谢大家提供的思路,验证了一下,这些思路都是可以实现的,试过HamilFei这位朋友加锁的思路是可以解决问题的。
2018.10.14
在查询数据库是否存在该userId前加锁吧。