MySQL采用order by limit分段取数据汇总错误问题探究

MySQL采用order by limit分段取数据汇总错误问题探究

背景

前几天接同事报问题:源数据一致的情况下,生产环境报表生成时而对,时而缺少确定的值。
查看源码,报表生成采用SQL语句,

create_time >= xxx and create_time <= yyy order by create_time limit offset, 1; 

每次取指定时间段的一条记录,然后累加指定字段生成。(先不考虑这种方式的效率)

结论

当多条记录的create_time相同时,数据按create_time排序的结果是不恒定的(没有幂等性);
导致有时某些记录被取出多次,某些记录没有取到,从而表现为报表时而对,时而缺少固定的值。

解决方案

分段取数据情况下,排序依据需要是具体唯一性的值,如数据库主键。保证每次排序结果恒定,幂等。
补充:分段取数据,通常有时间参数,且索引最好能命中时间参数;所以排序最好是时间参数, 数据库主键一起

过程

看代码

每次取一条,逻辑虽然奇葩,但细看代码无bug。

看日志

没有日志,想办法。以下是想办法过程:

  1. 初想用Btrace,不熟Btrace埋点语法和如何使用非JDK类,遂放弃。

  2. MyBatis Mapper文件默认有logger,级别是info;SpringBoot Admin可以动态开启指定logger;遂用SpringBoot Admin将对应Mapper日志级别设置为Trace。

  3. K8S指定pod日志重定向到文件 kubectl logs -f --tail=10 pod名称 > mapper.log

  4. 手动触发报表生成逻辑,grep、awk采集mapper.log中sql的参数和结果。

  5. excel排序对比数据库源数据和mapper.log采集的数据,找出差异:某条记录被取2次,某条记录未被取。

  6. 分析差异,被取2次记录A和未被取记录B的create_time相同,导致前一次获取排序A、B,后一次获取排序B、A;A被取2次,B未被取到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值