3.3.13偶发数据查询结果错误

为了更快的定位您的问题,请提供以下信息,谢谢
【详述】问题详细描述
【背景】凌晨查询结果和早上查询结果不一致
【业务影响】影响生产
【是否存算分离】
【StarRocks版本】例如:3.3.13
【集群规模】例如:3fe(1 follower+2observer)+3be(fe与be独立部署)
【机器信息】CPU虚拟核/内存/网卡,例如:16C/64G/万兆
【联系方式】为了在解决问题过程中能及时联系到您获取一些日志信息,请补充下您的联系方式,例如:社区群15-沐不木或者邮箱,谢谢
我有一张明细表 dm_08_loan_rcapi_d ,我凌晨会对这个表做t-2的数据统计并且写入到一张临时表里面,语句如下
insert overwrite mid.mid_08_loan_rcapi_d_temp8
select
A.LOANACNO
,current_timestamp() etldate
,SUM(A.RCAPI) RCAPI
,SUM(A.RINTE) RINTE
,SUM(A.RFINE) RFINE
,SUM(A.RFEE) RFEE
,SUM(A.MUIS_RFEE) MUIS_RFEE
FROM dm.dm_08_loan_rcapi_d A
WHERE A.WORKDATE2 < ‘2025-10-22’
GROUP BY A.LOANACNO
;
完成这个统计后,我会将t-1的业务数据同步写入到基础表dm_08_loan_rcapi_d

但是现在发现偶尔会出现早上通过上面的统计sql查询的结果和晚上使用这个sql写入到临时表mid_08_loan_rcapi_d_temp8的数据不一致,并且其中部分异常的数据一直没有过变动(也就是完成统计计算后插入t-1的数据就没有这一条的)但是凌晨和早上的结果也不一致,请问可能是什么问题呢,有什么排查思路吗?有可能是Compaction导致的问题吗

这是一个非常典型的 数据可见性(Data Visibility) 事务隔离 问题,在基于MVCC(多版本并发控制)的OLAP系统中,尤其是在数据加载和后台任务并发执行时,需要仔细排查。

1. Compaction是否是原因?

结论:Compaction(数据合并)本身导致数据不一致的可能性极低。

原因: StarRocks使用MVCC机制。当一个查询(包括您的 INSERT OVERWRITE 语句)开始执行时,它会锁定一个特定的数据版本(Snapshot)。Compaction是一个后台任务,它合并数据文件,但不会改变数据的逻辑内容,也不会影响正在运行的查询所读取的快照。只有当Compaction完成后,新的查询才会看到新的、合并后的版本。

因此,如果数据不一致,通常不是Compaction导致的,而是 数据加载或事务提交的时序 导致的。

2. 最可能的原因:T-2数据加载的可见性问题

您描述的现象——“凌晨写入的结果”和“早上查询的结果”不一致,且涉及的数据是T-2的、未变动的数据——最可能的原因是:

当凌晨的 INSERT OVERWRITE 任务开始执行时,前一天(T-2)的数据加载任务尚未完全提交或对查询不可见。

详细解释:

  1. T-2数据加载: 假设T-2的数据是在昨晚23:00开始加载到 dm.dm_08_loan_rcapi_d 表中。
  2. 凌晨统计开始: 您的 INSERT OVERWRITE 任务在00:00开始执行。
  3. 并发状态: 如果T-2的数据加载任务在00:00时尚未完成(即Load Job状态不是 FINISHED ),或者虽然数据已经写入但事务尚未完全提交,那么 INSERT OVERWRITE 任务读取到的数据可能是一个 不完整 的T-2快照。
  4. 早上查询: 到了早上,T-2的数据加载任务早已完成并提交。此时您手动执行 SELECT 语句,它读取的是一个 完整且最新 的快照。

结果: 凌晨的 INSERT OVERWRITE 遗漏了部分T-2的数据,导致统计结果偏低或不一致。

3. 排查思路和建议

针对上述最可能的原因,您可以按照以下步骤进行排查:

步骤一:检查T-2数据加载状态

这是最关键的一步。

  1. 确定T-2数据加载任务的结束时间: 找到将T-2数据写入 dm.dm_08_loan_rcapi_d 表的Load Job(无论是Broker Load, Routine Load, 或其他方式)。
  2. 检查Load Job状态: 使用 SHOW LOAD 命令(如果是异步加载)或查看相关日志,确认该Load Job的状态变为 FINISHED 的具体时间点 T_{load\_finish}
  3. 对比统计任务开始时间: 确认您的 INSERT OVERWRITE 任务的开始时间 T_{insert\_start}
  4. 判断: 如果 T_{insert\_start} 早于 T_{load\_finish} ,那么这就是导致数据不一致的直接原因。

解决方案: 确保您的统计任务( INSERT OVERWRITE )在所有前置数据加载任务 完全结束并提交 之后再开始执行。

步骤二:检查并发写入冲突

虽然可能性低于步骤一,但仍需检查。

  1. 检查并发写入: 在凌晨 INSERT OVERWRITE 任务执行期间,是否有其他任务正在对 dm.dm_08_loan_rcapi_d 表进行写入( INSERT INTOUPDATE )。
  2. 隔离级别: StarRocks默认提供快照隔离(Snapshot Isolation),这通常能保证读取一致性。但如果存在大量高并发的写入操作,并且这些操作涉及您查询的T-2分区,可能会引入极小的风险。

步骤三:隔离并分析异常数据

  1. 定位异常数据: 找出在凌晨临时表 ( mid_08_loan_rcapi_d_temp8 ) 中和早上查询结果中不一致的 LOANACNO 列表。
  2. 查询原始表: 针对这些异常的 LOANACNO ,分别在早上和凌晨(如果能重现)查询原始表 dm.dm_08_loan_rcapi_d 的明细数据:
-- 假设不一致的LOANACNO是 '123456'
SELECT * FROM dm.dm_08_loan_rcapi_d A
WHERE A.LOANACNO = '123456' AND A.WORKDATE2 < '2025-10-22';
  1. 对比明细: 比较两次查询返回的行数和总和是否一致。如果行数不一致,则确认了凌晨的 INSERT OVERWRITE 确实没有读取到全部数据。

总结建议

最稳妥的做法是 在调度层面增加依赖检查 。确保负责加载 dm.dm_08_loan_rcapi_d 表T-2数据的任务成功完成后,再触发 mid.mid_08_loan_rcapi_d_temp8 的统计任务。

如果您的数据加载是通过 StarRocks 的 Load Job 完成的,请务必检查 SHOW LOAD 结果,确保状态为 FINISHED

谢谢老师的答复,关于您提到的可能问题点,我这边做了排查
1.写入方式我这边是自己基于内部调度平台实现的sql执行的jar核心执行sql语句的部分如下:


因为基于这样的写入,所以无法在sr的内部找到对应的执行状态记录,但是有调度平台的日志信息如下:

展示已经执行完成并写入
我的建表语句属性如下:
企业微信截图_176128537319
理论上也不会存在主副本不一致的问题

单条数据校验这个,因为内部写入的数据不会再做修改(本身也是明细表),所以在我们发现数据异常后,筛选了一部分异常数据,是历史沉积很久的数据,都不在最新的分区的数据(t-1写入新数据只会在最新的当月的分区里面),他们也出现了汇总结果不一致的情况,所以我们这边感觉可以排除数据本身的问题

另外,这个查询的基础表不存在查询时写入的情况,仅仅在查询后会被写入