☰
Hive 源码导读(六):订单已经写出新文件,查询为什么还不能随便读?
2026/10/13 3:18:34 网站建设 项目流程

Hive 源码导读(六):订单已经写出新文件,查询为什么还不能随便读?

上一篇解释了锁:并发操作动手前,需要先按规则协调。

接着看一个更具体的业务变化。订单1001原来是已支付,金额99.00。后来发生退款,要把它的状态改成REFUNDED。

HDFS 上出现了新的数据文件。此时,另一个查询是不是扫描目录,把新旧文件里的内容全读出来就行?

如果这么做,同一笔订单可能被算两次,甚至把还没提交的修改算进日报。事务要回答的,正是“这次查询允许看到哪些内容”。

本文基于Hive 3.1.2、Hadoop 3.2.1,使用配置好的DbTxnManager 与 full ACID ORC 管理表。本文使用单语句隐式事务,不把多个独立 SQL 当作一笔多语句事务。目录名和时间线是机制示意,不是实测快照。

一、先把订单准备好

这一篇使用独立的orders_acid表。前几篇的orders_raw是非事务外部表,不能直接照搬本篇的 UPDATE。

完整建表和一次性初始化脚本在 实验准备。先查询目标订单:

SELECTorder_id,amount,statusFROMcsdn_hive_lab.orders_acidWHEREdt='2026-10-09'ANDorder_id=1001;

按系列样本,初始数据是:

order_idamountstatus
100199.00PAID

现在执行:

UPDATEcsdn_hive_lab.orders_acidSETstatus='REFUNDED'WHEREdt='2026-10-09'ANDorder_id=1001;

业务含义很简单:这笔订单不再进入已支付金额。系统内部却需要协调锁、写入标识、文件和提交状态。

二、锁和事务,各自管哪件事

可以把订单报表想成查账。

锁负责协调某些同时进行的操作:谁可以动哪一部分,哪些动作需要等待。

事务与可见性规则负责确定这次查账使用哪个有效版本:哪些写入已经成功,哪些仍未完成,哪些已经失败。

比如写入者正在准备退款信息,查询不应该因为在文件系统里碰巧看到了半路产生的文件,就把它当作已经完成的业务结果。

协调读写与选择可见版本,是两件配合完成的工作。

三、Txn ID 和 Write ID 为什么要分开

DbTxnManager.openTxn()通过 HMS 申请事务,并启动相关心跳。事务标识用于识别这次事务活动。

涉及某张事务表的写入,还会分配对应表的 Write ID。可以理解为:Txn ID 是事务的编号,Write ID 是这张表记录写入进度时使用的编号。

标识作用范围用处
Txn IDMetastore 事务体系识别事务与状态
Write ID表内写入序列判断该表上的写入版本与可见性
Statement ID同一写入上下文中的语句区分参与区分相应文件或写入动作

不要从delta_...目录里的数字直接推断它就是全局 Txn ID。两个编号即使在一个简单实验中刚好相等,也不代表概念相同。

四、文件写出来之后,还差什么

把正常写入路径压缩一下:

开启事务、确定读写上下文 → 编译与锁协调 → 执行写入,产生相应文件 → 查询执行成功 → 向 HMS 提交事务

真实实现还有快照校验、失败回滚等分支,这里只强调文件与提交的先后边界。

DbTxnManager.commitTxn()最终会调用:

getMS().commitTxn(txnId);

HMS 再交给TxnHandler.commitTxn()处理。某些并发写冲突,也需要在事务提交逻辑中检查。文件已经产生,不等于后续提交一定能成功。

如果事务失败,相关文件也不一定瞬间从磁盘消失。是否能被查询读取,依赖有效事务和写入信息;物理清理是另一个过程。

五、查询像拿着一份“本次可读名单”

Driver 会取得有效事务信息,并记录相关表的有效 Write ID 列表。可以把它理解为给本次查询划出一个读取边界,同时记录不应读取的写入。

它不只是一个最大的号码。某些编号可能仍在进行中,或已经中止,读取时也需要排除。

看一个明确标注条件的时间线:

时刻发生的事情
T1查询 Q1 已确定有效读取快照并开始读;快照不包含本次退款修改
T2写入者产生订单 1001 的退款相关文件,事务尚未提交
T3退款事务提交成功
T4新查询 Q2 取得包含这次提交的读取快照

在这个条件下,Q1 按它的快照读取旧的已支付状态,Q2 可以读取退款后的状态。Q1 不会仅仅因为读到一半发现事务提交了,就随意切换到另一套名单。

这里特意写“已确定并开始使用快照”,没有把客户端按回车的时刻当作快照建立时刻。Hive 3.1.2 的 Driver 在申请锁后还可能校验快照并重新编译,因此需要根据实际阶段判断。

六、base、delta、delete_delta 是怎样配合的

先记职责,不急着背目录命名规则:

类型大白话理解不能误解成什么
base整理到一定进度的基础数据每张新事务表从第一次写入就必然有 base
delta某段写入范围的增量内容目录里所有写入都一定对当前查询有效
delete_delta删除事件,用于使相应旧记录失效直接把旧数据文件立即删掉

Hive 3.1.2 的常见 full ACID split-update 路径,会把更新组织成对应旧记录的删除事件和新记录的插入。新旧文件可能同时存在,但读取层不会简单地把每一行全部累加。

AcidUtils.getAcidState()根据有效写入信息选择相关的基础文件和增量范围;ORC ACID 读取逻辑还会结合行标识、删除事件与有效 Write ID 处理记录。

因此,排查时只执行hdfs dfs -ls,看到目录里有几份文件,就直接判断“重复了几份数据”,是不够的。目录列表回答物理文件存在性,查询结果还受读取规则约束。

七、Compaction 是整理文件,不是替业务提交事务

增量文件越来越多,每次读取都要考虑更多文件和元数据,成本会增加。这时需要 Compaction 帮忙整理。

角色负责什么
Initiator检查哪些表或分区可能需要压缩整理,并发起相应请求
Worker执行压缩整理工作;也可以处理手工提交的压缩请求
Cleaner在满足安全条件后,清理不再需要的旧文件

Minor compaction 主要合并增量;major compaction 会进一步把相应内容整理到新的 base。具体适用范围与行为以本版本实现、表类型和配置为准。

整理完成后,旧文件也可能还要为旧快照保留一段时间。Cleaner 不能因为看见新 base,就无条件把所有旧目录删掉。

已提交数据的可见性不需要等待一次 compaction 才建立。Compaction 主要改善物理布局和后续读取成本,两者不要混成一个“最终生效开关”。

八、怎样验证订单状态发生了什么变化

普通练习可以先做串行验证:

  1. 确认使用 full ACID 表和正确事务管理器。
  2. 按主键条件查到订单 1001 的 PAID 状态。
  3. 执行文章开头的 UPDATE,确认语句成功完成。
  4. 用新发起的查询读取同一订单,核对 REFUNDED。
  5. 按分区重新计算已支付金额,与样本的预期变化对应。
SELECTSUM(amount)ASpaid_amountFROMcsdn_hive_lab.orders_acidWHEREdt='2026-10-09'ANDstatus='PAID';

六行原始样本中,已支付金额是299.00;将订单 1001 改为退款后,新的已支付金额应为200.00。这是根据样本算出的预期值,实际集群结果需要运行验证。

还可以查看:

SHOWTRANSACTIONS;SHOWCOMPACTIONS;

SHOW TRANSACTIONS不应当作所有历史已提交事务的完整审计表。要关联一次写入,还需要它对应的 Query ID、事务日志和表级信息。

若要验证“文件已产生但提交前不可见”,需要在隔离测试环境控制提交前的暂停位置,并保持心跳与查询线程工作;若要验证旧快照,还需确认 Q1 已固定并开始使用相应快照。本文没有执行这些并发控制实验,不把上面的时间线当成已经采集到的现场。

九、排障时,把三个证据放在一起

证据能说明什么
HDFS 文件与目录哪些物理文件已经存在
HMS 事务与锁信息写入、协调和提交目前处于什么状态
查询快照与最终结果当前查询允许读哪些内容,业务结果是否正确

单看其中一个,很容易下结论太早。

到这里,订单查询、MR 提交、锁和事务都已经串起来。最后一篇,我们面对一个没有提前公布原因的报表延迟,把这些知识变成一条真正能执行的排查路线。

本篇关键源码位置

  • DbTxnManager.openTxn()、commitTxn()、rollbackTxn():客户端事务生命周期。
  • Driver.recordValidWriteIds()与快照校验相关方法:查询有效读取信息。
  • TxnHandler.java:事务、Write ID 与提交检查。
  • AcidUtils.java、OrcRawRecordMerger:目录选择和记录可见性。
  • ql/.../txn/compactor/Initiator.java、Worker.java、Cleaner.java:压缩整理分工。

上一篇(后续更新,可从专栏目录查看) · 下一篇:订单日报延迟怎么查(后续更新,可从专栏目录查看)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询