2019-08-15 12:06:56 3008694 [http-nio-9983-exec-23] DEBUG c.d.f.course.dao.LeaguerDao.insert - ==>  Preparing: INSERT INTO leaguer (manager_user_id, leaguer_number, user_id, leaguer_level_id, buy_time, due_time, effective, buy_money, type, online_type, online_num, offline_type, offline_num, buy_type, order_id, source) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '430100004') 

2019-08-15 12:06:56 3008701 [http-nio-9983-exec-23] DEBUG c.d.f.course.dao.LeaguerDao.insert - ==> Parameters: (String), cqim@foxmail.com(String), 1745(String), 185(Integer), 2019-08-15 12:06:56(String), 2020-08-15 00:00:00(String), 1(Integer), 0.01(Double), 1(Integer), 1(String), null, 1(String), 10(Integer), 2(String), adb68450ecdc4b4f8b05ad1457220d6a(String)

2019-08-15 12:06:56 3008704 [http-nio-9983-exec-23] DEBUG c.d.f.course.dao.LeaguerDao.insert - <==    Updates: 1


2019-08-15 12:06:56 3008625 [http-nio-9983-exec-23] DEBUG c.d.f.c.dao.LeaguerDao.selectOne - ==>  Preparing: SELECT id, manager_user_id, user_id, leaguer_level_id, leaguer_number, buy_time, due_time, effective, buy_money, source, type, online_type, online_num, offline_type, offline_num, buy_type, order_id FROM leaguer WHERE leaguer.source = '430100004' AND user_id = ? AND order_id = ? 
2019-08-15 12:06:56 3008633 [http-nio-9983-exec-23] DEBUG c.d.f.c.dao.LeaguerDao.selectOne - ==> Parameters: 1745(String), adb68450ecdc4b4f8b05ad1457220d6a(String)
2019-08-15 12:06:56 3008636 [http-nio-9983-exec-23] DEBUG c.d.f.c.dao.LeaguerDao.selectOne - <==      Total: 0

目前的项目业务上使用了redission分布式锁,但是使用之后出现了插入数据库会出现插入两次的情况,业务流程具体是这样的,用户开通会员后,会插入一条数据到数据库,但是出现了插入了两条一模一样的数据情况,上面两条日志,第一个是第一次开通会员插入成功的日志 ,第二条是判断用户是否是会员,因为没查到数据,所以又插入了一遍数据库,这里问题就来了,第一条日志明明打出来数据插入成功了,为啥第二个请求过来了却查不到数据?仔细排查代码后发现了原来是事务提交的问题!

加锁操作放在了service层,方法上又加了@Transactional注解,每次return的时候释放锁,因为方法没执行完,事务并没有提交,这时候释放锁的一瞬间,第二个请求过来了,因为第二次请求和第一次的请求不属于同一个事务组,所以查不到刚才插入的数据,又会插入一遍数据,以至于最后return的时候方法执行完毕,提交事务,插入了两条数据!

解决方案:加锁和释放锁的操作放在controller层就行了

//  加锁

// do something

//  释放锁

Last modification:August 19th, 2019 at 04:34 pm