排行榜优化之-写读数据不一致问题排查
1️⃣、背景
在营销业务需求中,每个活动的参与用户拥有活动对应的资产,活动期间和活动结束后,在小程序页面都需要展示当前活动下的参与用户资产排行。
排序的逻辑是:用户的总资产+最先参与时间,总资产相同的情况下,最先参与活动的排前面。在活动期间,总资产会随着用户的动作动态变化。
界面展示如下:
2️⃣、实现方式
- 直接从数据库中,通过sql查询排序获取。这种方式实现起来简单,但是也有缺点:每次都从数据库中获取,单表数据量大的时候,查询,排序并不高效。
- 获取排行榜接口从redis中取前N排名,在资产管理类中新增事件监听当前用户的资产变化,及时更新到redis中。此种方案涉及到技术难点如下:
- 以什么样的数据结构存到redis中。
- redis的基于分数的有序集合,命令格式:(ZADD KEY_NAME SCORE1 VALUE1.. SCOREN VALUEN),可以看到此种数据结构是根据score的值来排序的,而我们的排序条件是个组合条件,如果用这种结构,需要一个算法把组合条件(total+time)的转成一个score值,并且这个value,我们需要存入当前参与用户对象的一些信息。
- 在翻看redisson 文档时发现reddisson支持sortset这样一种结构(https://github.com/redisson/redisson/wiki/7.-distributed-collections/#74-sortedset),背后的存入redis的其实是list,排序的方式可以自定义,这个list由reddssion维护,取出来就是已经排好序的列表,所以我选择了这种数据结构。
- 用户资产变化时怎么保持排名的正确性。用户资产变化存在以下几种情况。
- 用户资产变化,排名不变。并在TopN中。
- 用户资产变化,排名变更,名次还在TopN内.
- 用户资产变更,之前不在TopN,本次变更在TopN中。
- 用户资产变更,排名跌出TopN。缓存变更,当前用户剔除缓存,新用户加入topN。
- 以什么样的数据结构存到redis中。
3️⃣、发现问题
从实现方式可以知道,要通过redis来存当前活动的排行榜数据,需要逻辑来维护这份数据,因为用户的资产在活动期间是动态变化的。在代码中,当用户资产变化的时候,通过一个应用内异步事件拿当前变化的数据更新redis中的数据。实现代码如下:
public void assetsAdd(Long activityId, Long activityJoinId, ActivityAssetsLogEnums.AssetsLogType type, Integer assetsValue, AssetsCallback callback) throws BusinessException { //前置业务 AssetsCallbackResult callbackResult = callback.callback(); //资产添加成功 if (activityJoinDao.assetsIncr(activityJoinId,assetsValue)) { activityAssetsLogDao.addLog(activityId,activityJoinId,type.getCode(),assetsValue,callbackResult.getRemark(),callbackResult.getBizId()); //推送资产变更事件(异步) eventBusPublisher.publishAsync(new ActivityJoinAssertChangeEvent(activityId,activityJoinId, ActivityJoinEnums.AssertChangeType.ASSETS_ADD,assetsValue)); } else { throw BusinessExceptionFactory.create(BizErrorCodeEnum.ERROR_CODE_ACTIVITY_ASSETS_COMMON,"参与人不存在"); } } //资产变更事件监听 public void activityJoinAssertChange2Redis(ActivityJoinAssertChangeEvent event) { if (event.getAssertChangeType().equals(ActivityJoinEnums.AssertChangeType.ASSETS_CONSUME)) { return; } String key = String.format(USER_JOIN_ACTIVITY_ASSETS_RANK.getKey(), event.getActivityId()); RSortedSet<ActivityAssetsRankData> dataRSortedSet = redissonHelper.getRedissonClient().getSortedSet(key); //数据如果是空的不用管,在调用资产排行接口的时候会初始化 if (dataRSortedSet.isEmpty()) { return; } List<ActivityAssetsRankData> activityAssetsRankDataList = dataRSortedSet.readAll().stream().collect(Collectors.toList()); /******读取当前用户的资产********/ MmsActivityJoinEntity mmsActivityJoinEntity = activityJoinEntityMapper.selectByID(event.getActivityJoinId()); Optional<ActivityAssetsRankData> activityAssetsRankDataOptional = activityAssetsRankDataList.stream().filter(data -> data.getId().equals(event.getActivityJoinId())).findFirst(); ActivityAssetsRankData activityAssetsRankData = new ActivityAssetsRankData(); if (activityAssetsRankDataOptional.isPresent()) { activityAssetsRankData = activityAssetsRankDataOptional.get(); activityAssetsRankDataList.remove(activityAssetsRankData); } BeanUtils.copyProperties(mmsActivityJoinEntity, activityAssetsRankData); activityAssetsRankDataList.add(activityAssetsRankData); if (activityAssetsRankDataList.size() > rankConst) { activityAssetsRankDataList.sort(activityAssetsRankData); activityAssetsRankDataList = activityAssetsRankDataList.subList(0, rankConst); if (activityAssetsRankDataList.indexOf(activityAssetsRankData) != -1) { dataRSortedSet.clear(); dataRSortedSet.addAll(activityAssetsRankDataList); } } else { dataRSortedSet.clear(); dataRSortedSet.addAll(activityAssetsRankDataList); } } |
当用户资产变更是,发布异步事件,异步更新redis中的排行数据。这个逻辑看上去很美好,但是实际测试下来发现当用资产由10变成20时,异步逻辑中有几率读到的资产还是10?这样就导致缓存中数据不正确。
5️⃣、分析问题
出现这种问题需要从一下几个方面考虑:
- 主从同步延时问题,当更新了数据,马上查询,有可能更新了主库,而查询走从库,导致查询数据不一致。
- mybatis缓存问题,mybatis在查询条件一致的情况下,会优先从一级缓存中读取数据。
- 事物原因导致数据读取不一致。
6️⃣、排查问题
既然有了怀疑的对象,我们就开始一一排查。
- 主从同步
从配置中心看,数据库主从都是配的一个地址,并且指向的是ecs实例,因此可能不是主从同步问题导致。
- mybatis缓存问题
mybatis配置中,有是否开启缓存等配置,有全局的也有局部的,因此我在xml实现了这么一个查询配置(useCache="false" flushCache="true")不使用缓存,并且刷新缓存。
<select id="selectByID" resultMap="cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityMapper.BaseResultMap" useCache="false" flushCache="true"> select * from mms_activity_join where id=#{activityJoinId} </select> |
测试下来还是存在读取数据不一致。
- 事物
要分析是不是事物原因,我们要借助日志,因此首先需要打开相关的日志配置如下:
/**打开数据库操作日志*/ <Logger name="com.alibaba.druid" level="DEBUG" additivity="false"> <AppenderRef ref="STDOUT"/> <AppenderRef ref="JAR_LOG_FILE"/> </Logger> <Logger name="org.mybatis.spring" level="DEBUG" additivity="false"> <AppenderRef ref="STDOUT"/> <AppenderRef ref="JAR_LOG_FILE"/> </Logger> <Logger name="tk.mybatis" level="DEBUG" additivity="false"> <AppenderRef ref="STDOUT"/> <AppenderRef ref="JAR_LOG_FILE"/> </Logger> <Logger name="org.apache.ibatis" level="DEBUG" additivity="false"> <AppenderRef ref="STDOUT"/> <AppenderRef ref="JAR_LOG_FILE"/> </Logger> /**关闭缓存同步日志*/ <Logger name="cn.mwee.base_common.cache.CachePoolHelper" level="INFO" additivity="false" > </Logger> |
-
- 第一步:代码中加入日志打印,
- 在资产变更的方法中通过mapper查询当前用户的资产数据,并打印日志。
- 在事件监听方法中通过mapper查询当前用户资产数据,并打印日志。
发奖流程:
得到的日志内容如下:
10:28:38,161 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Creating a new SqlSession 10:28:38,162 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@9468e6e] was not registered for synchronization because synchronization is not active 10:28:38,197 <org.mybatis.spring.transaction.SpringManagedTransaction> DEBUG [http-nio-3081-exec-15]: JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@233e4356] will not be managed by Spring 10:28:38,231 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-15]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityExtMapper.selectByExample], SELECT id,activity_id,activity_type,user_id,user_mobile,user_name,head_img,platform,user_open_id,user_union_id,user_level,state,fission_assist_user_count,fission_assist_user_success_count,prize_draw_state,share_qrcode,join_group,join_group_id,join_code,inviter_join_id,order_count,order_amount,activity_assets_total,activity_assets_used,create_time,update_time FROM mms_activity_join WHERE ( ( activity_id = 4001 and user_id = 2035654811 ) ) order by id desc, Spend Time ===> 64 ms 10:28:38,231 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@9468e6e] 10:28:38,521 <cn.mwee.msh.mms.biz.handler.AbstractHandler> INFO [http-nio-3081-exec-15]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], 转盘抽奖-中奖日志:请求参数{\"activityId\":4001,\"cityId\":258,\"clientIp\":\"39.144.43.212\",\"platform\":\"wechat\",\"shareJoinId\":0,\"unionId\":\"o9BuWjod_YGPlYnBRWKbaspOrr9w\",\"userId\":2035654811,\"userMobile\":\"13788984575\",\"userName\":\"A.祢「一人心」.A11\",\"userOpenId\":\"oSj7-48oOMprjTbtgOBEjhvmRwa4\"},抽中奖品{\"activityId\":4001,\"createTime\":1663732185000,\"id\":8356,\"prizeDrawCondition\":\"\",\"prizeDrawTimesLimit\":0,\"prizeInventoryTotal\":0,\"prizeInventoryUsed\":0,\"prizeLevel\":1,\"prizeName\":\"吃货币\",\"prizeOps\":\"\",\"prizePercent\":10.00,\"prizePic\":\"\",\"prizePosition\":5,\"prizePrice\":0,\"prizeQuantity\":10,\"prizeRemark\":\"\",\"prizeShowCondition\":\"\",\"prizeType\":\"asset_coin\",\"prizeValue\":\"\"} 创建事物🔵10:28:38,663 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Creating a new SqlSession 注册事物🔵10:28:38,664 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] 10:28:38,666 <org.mybatis.spring.transaction.SpringManagedTransaction> DEBUG [http-nio-3081-exec-15]: JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5f1edc47] will be managed by Spring 增加资产🔴10:28:38,706 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-15]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityExtMapper.assetsIncr], UPDATE mms_activity_join SET activity_assets_total = activity_assets_total+10 WHERE id = 259242, Spend Time ===> 41 ms, Affect Count ===> 1 10:28:38,706 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] 10:28:38,707 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] from current transaction 10:28:38,737 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-15]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityExtMapper.selectByID], select * from mms_activity_join where id=259242, Spend Time ===> 30 ms 10:28:38,738 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] 打印用户资产🔴10:28:38,740 <cn.mwee.msh.mms.biz.service.ActivityAssetsBizService> INFO [http-nio-3081-exec-15]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], mmsActivityJoinEntity-assetsAdd=>{\"activityAssetsTotal\":40,\"activityAssetsUsed\":0,\"activityId\":4001,\"activityType\":\"rotaryDraw\",\"createTime\":1663811353000,\"fissionAssistUserCount\":0,\"fissionAssistUserSuccessCount\":0,\"id\":259242,\"inviterJoinId\":0,\"joinCode\":\"4001\",\"joinGroup\":0,\"orderAmount\":0,\"orderCount\":0,\"platform\":\"wechat\",\"prizeDrawState\":1,\"shareQrcode\":\"\",\"state\":2,\"userId\":2035654811,\"userLevel\":0,\"userMobile\":\"13788984575\",\"userName\":\"A.祢「一人心」.A11\",\"userOpenId\":\"oSj7-48oOMprjTbtgOBEjhvmRwa4\",\"userUnionId\":\"o9BuWjod_YGPlYnBRWKbaspOrr9w\"} 使用当前事物🔴10:28:38,741 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] from current transaction 写入资产日志🔴10:28:38,805 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-15]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityAssetsLogEntityExtMapper.insertSelective], INSERT INTO mms_activity_assets_log ( id,activity_id,activity_join_id,type,assets_value,remark,biz_id,create_time ) VALUES( 112896,4001,259242,'exchange_prize',10,'活动中奖,系统发放吃货币','','2022-09-22 10:28:38' ), Spend Time ===> 64 ms, Affect Count ===> 1 10:28:38,806 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] 10:28:38,808 <cn.mwee.msh.mms.common.eventbus.IMmsEventListener> INFO [mwee-pool-asyncEventBusThread-thread-0]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], event listener ActivityEventListener_activityJoinAssertChangeEventListener receive event :{\"activityId\":4001,\"activityJoinId\":259242,\"assertChangeType\":\"ASSETS_ADD\",\"assetsValue\":10,\"eventId\":\"20220922_102838140_442955ab6f48498c902054c31320d8d3\"} 10:28:38,809 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] from current transaction 创建事物⚫️10:28:38,878 <org.mybatis.spring.SqlSessionUtils> DEBUG [mwee-pool-asyncEventBusThread-thread-0]: Creating a new SqlSession ⚫️10:28:38,879 <org.mybatis.spring.SqlSessionUtils> DEBUG [mwee-pool-asyncEventBusThread-thread-0]: SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@23a455e7] was not registered for synchronization because synchronization is not active 写入发奖记录🔴10:28:38,899 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-15]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityPrizeDrawEntityExtMapper.insertSelective], INSERT INTO mms_activity_prize_draw ( id,activity_id,activity_join_id,user_id,user_mobile,user_name,fetch_time,fetch_source,fetch_source_id,fetch_source_remark,prize_id,prize_type,prize_value,state,create_time ) VALUES( 292487,4001,259242,2035654811,'13788984575','A.祢「一人心」.A11','2022-09-22 10:28:38','','','',8356,'asset_coin','10',0,'2022-09-22 10:28:38' ), Spend Time ===> 78 ms, Affect Count ===> 1 释放事物🔵10:28:38,899 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] 提交事物🔵10:28:38,903 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] 打印事物🔵10:28:38,903 <org.mybatis.spring.transaction.SpringManagedTransaction> DEBUG [mwee-pool-asyncEventBusThread-thread-0]: JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@233e4356] will not be managed by Spring 卸载事物🔵10:28:38,903 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] 关闭事物🔵10:28:38,903 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-15]: Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29b92da1] 查询当前用户资产⚫️10:28:38,926 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [mwee-pool-asyncEventBusThread-thread-0]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityExtMapper.selectByID], select * from mms_activity_join where id=259242, Spend Time ===> 45 ms 关闭事物⚫️10:28:38,926 <org.mybatis.spring.SqlSessionUtils> DEBUG [mwee-pool-asyncEventBusThread-thread-0]: Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@23a455e7] 打印用户资产⚫️10:28:38,927 <cn.mwee.msh.mms.biz.service.ActivityJoinBizService> INFO [mwee-pool-asyncEventBusThread-thread-0]: TraceID[20220922_102838140_442955ab6f48498c902054c31320d8d3], mmsActivityJoinEntity=>{\"activityAssetsTotal\":30,\"activityAssetsUsed\":0,\"activityId\":4001,\"activityType\":\"rotaryDraw\",\"createTime\":1663811353000,\"fissionAssistUserCount\":0,\"fissionAssistUserSuccessCount\":0,\"id\":259242,\"inviterJoinId\":0,\"joinCode\":\"4001\",\"joinGroup\":0,\"orderAmount\":0,\"orderCount\":0,\"platform\":\"wechat\",\"prizeDrawState\":1,\"shareQrcode\":\"\",\"state\":2,\"userId\":2035654811,\"userLevel\":0,\"userMobile\":\"13788984575\",\"userName\":\"A.祢「一人心」.A11\",\"userOpenId\":\"oSj7-48oOMprjTbtgOBEjhvmRwa4\",\"userUnionId\":\"o9BuWjod_YGPlYnBRWKbaspOrr9w\"} |
从日志中我们可以看到,
🔴的记录,在资产变更的逻辑中读取到的用资产是40,而在异步事件监听中读到了30。
🔵看出从抽奖-资产变更-发奖,都在一个事物中。
⚫️异步监听中创建了一个新的事物,发奖事物提交在异步监听事物后面。
所以极有可能是mysql的事物隔离导致数据读取不一致的问题,然后查看下当前数据库的事物隔离级别:
show variables like '%isolation%',当前数据库的事物隔离级别为:READ-COMMITTED,表示B事物能读到A事物的提交后的数据。也就能解释为什么异步监听中读不到最新的数据,因为异步监听触发后,资产变更事务未提交。
7️⃣、解决问题
从上面我们得知问题的原因,由此可以知道要解决当前问题有几种方式:
- 在资产变更事务中,查询当前用的资产数据作为参数,传到异步事件中。
- 更新用户资产的逻辑,开启一个新的事物,完成更新并提交。
- 更新用户资产的逻辑事物配置为PROPAGATION_NOT_SUPPORTED,即当前逻辑不使用事物提交。
分析下来:个人觉得方式1能解决当前问题,方式2能解决资产变更逻辑中读取不一致的问题。因此采用方式2来解决。
public boolean assetsIncr(Long id,Integer assetsValue) { DefaultTransactionDefinition defaultTransactionDefinition= new DefaultTransactionDefinition(); defaultTransactionDefinition.setPropagationBehavior(PROPAGATION_REQUIRES_NEW); TransactionStatus status = platformTransactionManager.getTransaction(defaultTransactionDefinition); boolean success=false; try { success= mapper.assetsIncr(id, assetsValue) > 0; platformTransactionManager.commit(status); } catch (Exception e) { platformTransactionManager.rollback(status); throw e; } return success; } |
日志输出如下:
12:59:58,726 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Creating a new SqlSession 12:59:58,728 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4c39e382] was not registered for synchronization because synchronization is not active 12:59:58,742 <org.mybatis.spring.transaction.SpringManagedTransaction> DEBUG [http-nio-3081-exec-14]: JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@233e4356] will not be managed by Spring 12:59:58,761 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-14]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityExtMapper.selectByExample], SELECT id,activity_id,activity_type,user_id,user_mobile,user_name,head_img,platform,user_open_id,user_union_id,user_level,state,fission_assist_user_count,fission_assist_user_success_count,prize_draw_state,share_qrcode,join_group,join_group_id,join_code,inviter_join_id,order_count,order_amount,activity_assets_total,activity_assets_used,create_time,update_time FROM mms_activity_join WHERE ( ( activity_id = 4001 and user_id = 2035654813 ) ) order by id desc, Spend Time ===> 29 ms 12:59:58,761 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4c39e382] 12:59:58,976 <cn.mwee.msh.mms.biz.handler.AbstractHandler> INFO [http-nio-3081-exec-14]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], 转盘抽奖-中奖日志:请求参数{\"activityId\":4001,\"cityId\":258,\"clientIp\":\"39.144.43.212\",\"platform\":\"wechat\",\"shareJoinId\":0,\"unionId\":\"o9BuWjod_YGPlYnBRWKbaspOrr9w\",\"userId\":2035654813,\"userMobile\":\"13788984575\",\"userName\":\"A.祢「一人心」.A13\",\"userOpenId\":\"oSj7-48oOMprjTbtgOBEjhvmRwa4\"},抽中奖品{\"activityId\":4001,\"createTime\":1663732185000,\"id\":8357,\"prizeDrawCondition\":\"\",\"prizeDrawTimesLimit\":0,\"prizeInventoryTotal\":0,\"prizeInventoryUsed\":0,\"prizeLevel\":1,\"prizeName\":\"吃货币\",\"prizeOps\":\"\",\"prizePercent\":10.00,\"prizePic\":\"\",\"prizePosition\":6,\"prizePrice\":0,\"prizeQuantity\":10,\"prizeRemark\":\"\",\"prizeShowCondition\":\"\",\"prizeType\":\"asset_coin\",\"prizeValue\":\"\"} 🔴12:59:59,050 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Creating a new SqlSession 🔴12:59:59,051 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5d277e63] 🔴12:59:59,053 <org.mybatis.spring.transaction.SpringManagedTransaction> DEBUG [http-nio-3081-exec-14]: JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@45d6d9f6] will be managed by Spring 🔴12:59:59,091 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-14]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityExtMapper.assetsIncr], UPDATE mms_activity_join SET activity_assets_total = activity_assets_total+10 WHERE id = 259248, Spend Time ===> 40 ms, Affect Count ===> 1 🔴12:59:59,091 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5d277e63] 🔴12:59:59,091 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5d277e63] 🔴12:59:59,092 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5d277e63] 🔴12:59:59,092 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5d277e63] 🔵12:59:59,150 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Creating a new SqlSession 🔵12:59:59,151 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] 🔵12:59:59,151 <org.mybatis.spring.transaction.SpringManagedTransaction> DEBUG [http-nio-3081-exec-14]: JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5f1edc47] will be managed by Spring 🔵12:59:59,175 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-14]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityExtMapper.selectByID], select * from mms_activity_join where id=259248, Spend Time ===> 24 ms 🔵12:59:59,176 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] 🔵12:59:59,176 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] from current transaction 🔵12:59:59,226 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-14]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.🔵MmsActivityAssetsLogEntityExtMapper.insertSelective], INSERT INTO mms_activity_assets_log ( id,activity_id,activity_join_id,type,assets_value,remark,biz_id,create_time ) VALUES( 112984,4001,259248,'exchange_prize',10,'活动中奖,系统发放吃货币','','2022-09-22 12:59:59' ), Spend Time ===> 48 ms, Affect Count ===> 1 🔵12:59:59,226 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] ⚫️12:59:59,227 <cn.mwee.msh.mms.common.eventbus.IMmsEventListener> INFO [mwee-pool-asyncEventBusThread-thread-0]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], event listener ActivityEventListener_activityJoinAssertChangeEventListener receive event :{\"activityId\":4001,\"activityJoinId\":259248,\"assertChangeType\":\"ASSETS_ADD\",\"assetsValue\":10,\"eventId\":\"20220922_125958686_6c407706d94245e2acd5710bfde7253b\"} 🔵12:59:59,227 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] from current transaction ⚫️12:59:59,274 <org.mybatis.spring.SqlSessionUtils> DEBUG [mwee-pool-asyncEventBusThread-thread-0]: Creating a new SqlSession ⚫️12:59:59,275 <org.mybatis.spring.SqlSessionUtils> DEBUG [mwee-pool-asyncEventBusThread-thread-0]: SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5f64ecb7] was not registered for synchronization because synchronization is not active 🔵12:59:59,293 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [http-nio-3081-exec-14]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityPrizeDrawEntityExtMapper.insertSelective], INSERT INTO mms_activity_prize_draw ( id,activity_id,activity_join_id,user_id,user_mobile,user_name,fetch_time,fetch_source,fetch_source_id,fetch_source_remark,prize_id,prize_type,prize_value,state,create_time ) VALUES( 292521,4001,259248,2035654813,'13788984575','A.祢「一人心」.A13','2022-09-22 12:59:59','','','',8357,'asset_coin','10',0,'2022-09-22 12:59:59' ), Spend Time ===> 60 ms, Affect Count ===> 1 🔵12:59:59,293 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] 🔵12:59:59,294 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] 🔵12:59:59,300 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] 🔵12:59:59,301 <org.mybatis.spring.SqlSessionUtils> DEBUG [http-nio-3081-exec-14]: Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@81f1d95] ⚫️12:59:59,301 <org.mybatis.spring.transaction.SpringManagedTransaction> DEBUG [mwee-pool-asyncEventBusThread-thread-0]: JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@233e4356] will not be managed by Spring ⚫️12:59:59,318 <cn.mwee.base_common.helper.mybatis.plugins.SqlInterceptor> INFO [mwee-pool-asyncEventBusThread-thread-0]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], Mapper Method ===> [cn.mwee.msh.mms.data.mapper.MmsActivityJoinEntityExtMapper.selectByID], select * from mms_activity_join where id=259248, Spend Time ===> 42 ms ⚫️12:59:59,318 <org.mybatis.spring.SqlSessionUtils> DEBUG [mwee-pool-asyncEventBusThread-thread-0]: Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5f64ecb7] ⚫️12:59:59,325 <cn.mwee.msh.mms.biz.service.ActivityJoinBizService> INFO [mwee-pool-asyncEventBusThread-thread-0]: TraceID[20220922_125958686_6c407706d94245e2acd5710bfde7253b], mmsActivityJoinEntity=>-activityJoinEntityMapper{\"activityAssetsTotal\":200,\"activityAssetsUsed\":0,\"activityId\":4001,\"activityType\":\"rotaryDraw\",\"createTime\":1663817915000,\"fissionAssistUserCount\":0,\"fissionAssistUserSuccessCount\":0,\"id\":259248,\"inviterJoinId\":0,\"joinCode\":\"4001\",\"joinGroup\":0,\"orderAmount\":0,\"orderCount\":0,\"platform\":\"wechat\",\"prizeDrawState\":1,\"shareQrcode\":\"\",\"state\":2,\"userId\":2035654813,\"userLevel\":0,\"userMobile\":\"13788984575\",\"userName\":\"A.祢「一人心」.A13\",\"userOpenId\":\"oSj7-48oOMprjTbtgOBEjhvmRwa4\",\"userUnionId\":\"o9BuWjod_YGPlYnBRWKbaspOrr9w\"} |
8️⃣、总结&思考
在业务中使用事物,需要多关注事物传播和事物隔离级别的问题。
在更新用户的资产直接使用@Transactional行不行?
spring的事物隔离级别与数据的的隔离级别不一致会有什么问题?