订阅更新

离线作业失败下游已出报表——数据故障止损与回滚SOP

数据质量手册 第 13 题 约 9 分钟读完

本文目录
  1. 先说结论
  2. 第一步:止血(5分钟内)
  3. 第二步:评估(10-15分钟)
  4. 第三步:通知(20分钟内)
  5. 第四步:修复(按故障类型)
  6. 第五步:复盘(24小时内)
  7. 故障的预防性回滚机制
  8. 面试高频追问
  9. 实战踩坑:一次「修着修着把好的数据也覆盖了」
  10. 总结

先说结论

数据故障处理黄金五步法:①止血(阻止扩散)→ ②评估(影响面+严重度)→ ③通知(业务+管理层)→ ④修复(数据+流程)→ ⑤复盘(预防再次)。每一步都有明确的SLA。

最容易做错的是顺序:很多人发现问题第一反应是「我赶紧改」,结果改的过程中下游又消费了错误数据,影响面扩大3倍。先止血再修复,这是铁律。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

「凌晨3点ETL跑挂了,老板早上要看的报表已经发到群里了,数字是错的——怎么办?」这是数据团队最高压的场景。这道题考的不是技术,是应急能力。处理对了能体现Tech Lead级别的判断力,处理错了直接让事故升级。我在当前出海短剧公司值班期间处理过几次P0级数据故障,今天梳理一套实战SOP。

第一步:止血(5分钟内)

发现问题后第一件事不是修,是阻止扩散。三个动作并行:

# 1. 阻断下游调度
block_downstream_tasks(faulty_table)
# DataWorks/DolphinScheduler都有「冻结下游」操作
 
# 2. 撤回已经分发的报表(如果可能)
if report_already_sent:
    notify_business_to_disregard(report_id)
    # 钉钉/邮件撤回
 
# 3. 标记数据为「不可消费」状态
mark_table_status(faulty_table, 'INVALID')
# 通过元数据系统让BI/服务API感知到

我在出海硬件公司处理过一次故障:发现的时候已经凌晨5点,立刻联系运营团队不要发早会PPT、把昨晚提前定时发出的Email标记「数据有误请勿使用」。这一步比修数据重要——错误数据一旦被业务用于决策就回不了头了。

第二步:评估(10-15分钟)

止血之后立刻评估三个问题:

维度评估内容工具
影响面哪些下游表/报表/服务被污染数据血缘
严重度影响是否触及P0业务(财务/合规/对外)业务关键性矩阵
可恢复性数据能不能修复,需要多久故障类型分析
-- 用血缘快速找到下游影响面
WITH RECURSIVE downstream AS (
  SELECT downstream_table AS tbl, 1 AS depth
  FROM lineage WHERE upstream_table = 'dwd_order'  -- 故障源表
  UNION ALL
  SELECT l.downstream_table, d.depth + 1
  FROM lineage l JOIN downstream d ON l.upstream_table = d.tbl
  WHERE d.depth < 5
)
SELECT tbl, depth, owner, business_criticality
FROM downstream JOIN table_meta ON tbl = table_name
ORDER BY business_criticality DESC, depth ASC;
-- 优先级:高criticality + 浅depth = 最先要修复的

第三步:通知(20分钟内)

通知不是越早越好,是「评估清楚后立刻」。一份合格的故障通知必须包含:

# 故障通知模板
【数据故障通报-P1】
  
故障时间:2024-03-15 03:00 至 排查中
故障表:dwd_order
影响范围:
  - 下游15张表(详见附件)
  - 涉及报表:日订单看板、GMV周报、运营投放ROI
  - 影响业务:订单中心、广告投放团队
  
已采取措施:
  - 已阻断所有下游调度
  - 已通知报表使用方暂不使用今日数据
  
预计修复时间:上午11点前
  
影响评估:业务可使用昨日数据替代,无重大决策依赖
  
联系人:Wood(数据团队值班)

通知的关键不是「我们出事了」,是「我们知道范围、我们在处理、什么时候修复」——给业务方明确预期。最忌讳的是「我们在查」这种没有信息量的回复。

第四步:修复(按故障类型)

故障类型典型表现修复方式
数据丢失数据量比基线少30%+重跑分区/补数
数据重复主键去重后量级翻倍INSERT OVERWRITE重写
数据错误金额/状态字段值不对修复SQL+回算下游
数据延迟数据没到等上游恢复+重算
数据污染脏数据混入历史回滚到上一稳定版本

修复时的关键原则:

• 永远先在测试环境验证修复SQL再上生产

• 修复脚本必须幂等(重跑多次结果一致)

• 修复完一张表立刻DQC校验通过再放下游

-- 标准修复模板:先备份、再OVERWRITE、最后DQC
-- 1. 备份当前异常分区
CREATE TABLE dwd_order_backup_20240315 AS
SELECT * FROM dwd_order WHERE dt = '20240315';
 
-- 2. 用修正逻辑OVERWRITE
INSERT OVERWRITE TABLE dwd_order PARTITION(dt='20240315')
SELECT order_id, user_id, amount,
       /* 修正状态字段:NULL → 'unknown' */
       COALESCE(status, 'unknown') AS status
FROM ods_order WHERE dt = '20240315';
 
-- 3. DQC校验
SELECT COUNT(*) AS total,
       COUNT(*) FILTER (WHERE status IS NULL) AS null_status
FROM dwd_order WHERE dt = '20240315';
-- 必须全部=0通过才能放开下游
 
-- 4. 触发下游重跑
-- DataWorks: 「补数据」操作,按血缘顺序重跑

第五步:复盘(24小时内)

故障处理完不算结束,必须复盘。一份合格的复盘报告含5要素:

1. 时间线(精确到分钟)

2. 根因分析(5 Whys)

3. 影响评估(量化损失)

4. 改进措施(防止再次发生)

5. ActionItems(含负责人和DDL)

我在出海硬件公司养成习惯——每次P1+故障都写复盘文档放Confluence,半年累积30+篇,新人入职先读。比任何培训都有效。

故障的预防性回滚机制

最优秀的故障处理是「能秒级回滚」。两种实现方式:

-- 方式1:Delta Lake/Iceberg的Time Travel
-- 任何错误写入都可以一行SQL回滚
RESTORE TABLE dwd_order TO VERSION AS OF 42;
-- 或按时间
RESTORE TABLE dwd_order TO TIMESTAMP AS OF '2024-03-14 23:00:00';
 
-- 方式2:每次OVERWRITE前自动备份
-- 通过自定义UDF或调度系统钩子实现
-- 例如:dwd_order_history 表保留最近7天每个版本

面试高频追问

追问一:怎么判断要不要回滚?

看「修复成本 vs 数据损失」。如果修复时间>2小时且影响面大,立刻回滚到上一稳定版本(接受少量数据损失);如果影响小且明确知道修复方式,就地修复。生产实践中我用的判断标准:影响P0业务且修复时间不可预估 → 回滚;影响P1+修复路径明确 → 修复。

追问二:业务方一直追着问,怎么和他们沟通?

永远主动通知比被问强。固定节奏:发现5分钟、评估完20分钟、每30分钟更新一次进展、修复完立刻通知。哪怕「还在查」也要每30分钟说一次「还在查,目前看是XX方向」。沉默是事故升级的最大原因。

追问三:怎么避免下次再发生?

三个层次:①补DQC规则(这次没拦住的下次能拦);②加监控(基础设施层、数据层、业务层);③改流程(review、灰度、上线检查)。复盘报告里的Action Items必须落到这三个层次至少各一项,否则不算合格复盘。

实战踩坑:一次「修着修着把好的数据也覆盖了」

出海硬件公司有次发现某表昨天分区数据量异常少(只有平时1/3)。我火急火燎写了修复SQL,写完没仔细检查WHERE条件,直接INSERT OVERWRITE跑下去——结果把过去7天的分区全覆盖了,因为我那条SQL的WHERE条件少了一个分区限定。

-- 我跑的错误SQL(SQL正确,但WHERE条件没限定分区)
INSERT OVERWRITE TABLE dwd_order  -- 没指定 PARTITION(dt='20240315')
SELECT ... FROM ods_order WHERE dt >= '20240310';
-- 结果:把20240310-20240315全部分区覆盖
-- 之前没问题的6天数据全被错误SQL覆盖

解决方案:紧急切到Delta Lake的Time Travel回滚到出问题前的版本,损失30分钟数据但避免了7天数据全毁。事后定了三条铁律:

1)所有手动修复SQL必须有reviewer +1才能跑

2)OVERWRITE分区表必须显式写PARTITION子句

3)核心表全部接Delta Lake/Iceberg保留Time Travel历史

教训:故障处理的二次伤害比首次故障更严重。越是高压越要冷静,必要时多花5分钟review SQL,比快速跑错代价低100倍。

总结

数据故障五步法:止血→评估→通知→修复→复盘。核心是顺序——先阻止扩散再修复。配合Time Travel等预防性回滚机制,把故障MTTR控制在小时级。面试时按五步法+真实故障故事讲,能秀出实战水平和Tech Lead思维。

下一篇聊一个补数最容易翻车的话题:补数/回刷把历史数据搞乱了——重跑机制怎么设计才安全?

你们经历过最严重的数据故障是什么?怎么处理的?评论区聊聊~

关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长

刷题进度保存在当前浏览器