Azure Databricks中Auto OPTIMIZE引发Delta表数据不一致问题排查
问题描述
在Azure Databricks中,某Delta表每10分钟执行一次MERGE操作。从版本历史可见,每3-4次MERGE后会触发一次由Databricks预测式优化机制自动执行的OPTIMIZE操作。
当前遇到的问题:执行带WHERE子句的简单SELECT查询时,会随机出现数据不一致(记录数少于预期)的情况,且该问题仅发生在OPTIMIZE执行期间,疑似合并小文件的过程中影响了数据一致性。
相关操作指标
OPTIMIZE操作指标
numRemovedFiles: "2" numRemovedBytes: "5644151" p25FileSize: "3234772" numDeletionVectorsRemoved: "1" minFileSize: "3234772" numAddedFiles: "1" maxFileSize: "3234772" p75FileSize: "3234772" p50FileSize: "3234772" numAddedBytes: "3234772"
MERGE操作指标(OPTIMIZE执行前10秒)
numTargetRowsCopied: "0" numTargetRowsDeleted: "0" numTargetFilesAdded: "1" numTargetBytesAdded: "2409613" numTargetBytesRemoved: "0" numTargetDeletionVectorsAdded: "1" numTargetRowsMatchedUpdated: "20380" executionTimeMs: "22332" materializeSourceTimeMs: "5886" numTargetRowsInserted: "6" numTargetRowsMatchedDeleted: "0" numTargetDeletionVectorsUpdated: "0" scanTimeMs: "1781" numTargetRowsUpdated: "20380" numOutputRows: "20386" numTargetDeletionVectorsRemoved: "0" numTargetRowsNotMatchedBySourceUpdated: "0" numTargetChangeFilesAdded: "1" numSourceRows: "20386" numTargetFilesRemoved: "0" numTargetRowsNotMatchedBySourceDeleted: "0" rewriteTimeMs: "14510"
问题原因与配置排查
可能原因
删除向量(DV)与OPTIMIZE的并发冲突
MERGE操作通过添加删除向量(DV)标记需更新的旧行(避免重写大文件),随后自动OPTIMIZE触发,在将DV应用到数据文件并生成新文件的过程中,若查询恰好读取到DV已被移除但新文件尚未完全写入提交的中间状态,会导致部分行被遗漏。尽管Delta Lake保证ACID原子性,但后台异步OPTIMIZE的事务处理边缘场景可能引发该问题。查询隔离级别配置异常
若查询使用了READ UNCOMMITTED等非默认隔离级别,可能读取到OPTIMIZE未提交的中间数据,导致结果异常。Delta Lake默认隔离级别为SERIALIZABLE,若该配置被修改,会破坏ACID特性的保证。元数据更新延迟
OPTIMIZE在移除旧文件、添加新文件时,事务日志的更新可能存在短暂延迟,导致查询读取到过时的元数据:要么认为已被移除的旧文件仍存在,要么未识别到刚写入的新文件,最终扫描的文件不完整,导致记录数不足。
配置排查方向
- 检查表隔离级别:执行
DESCRIBE EXTENDED <table_name>,查看Isolation Level字段,确认是否为默认的SERIALIZABLE。若为其他级别,需修改回默认值。 - 核查自动优化配置:查看表属性
delta.autoOptimize.optimizeWrite和delta.autoOptimize.autoCompact的状态,同时确认Databricks Runtime版本是否在8.3及以上(预测式优化的最低支持版本)。 - 确认查询版本读取逻辑:检查查询是否使用了
VERSION AS OF或TIMESTAMP AS OF指定旧版本,确保默认读取最新已提交版本。 - 排查OPTIMIZE事务日志:查看OPTIMIZE操作的完整事务日志,确认是否存在事务失败、文件写入不完整等异常情况。
- 调整自动OPTIMIZE触发阈值:通过修改表属性
delta.autoOptimize.minFileSize或delta.autoOptimize.maxFileCount,推迟OPTIMIZE的触发时机,避免在MERGE完成后立即执行优化。
内容的提问来源于stack exchange,提问作者Sanket Kelkar
相关产品推荐
相关产品推荐

