跳转至

大数据量增量更新实践

一、业务场景

背景

  • 订单明细表:6000万行数据

  • 数据特点:历史数据可能被更新(几个月前的数据)

  • 存在硬删除:源表数据会被物理删除

  • 数据源:MySQL只读备库,性能受限

  • 更新标识:lastUpdated时间戳字段

核心需求

  • 基于时间戳识别增量数据

  • 支持增量更新(INSERT/UPDATE)

  • 支持硬删除同步


二、方案对比

工作原理

MySQL Binlog → Flink CDC → Iceberg表
捕获: INSERT/UPDATE/DELETE事件

优势

  • ✅ 完美支持所有变更类型(增删改)

  • ✅ 运行时对源库压力小(仅读binlog)

  • ✅ 实时性好,自动捕获变更

  • ✅ 支持历史数据回溯更新

风险

  • ⚠️ 首次全量同步压力大(6000万数据预计需4-8小时)

  • ⚠️ 对性能差的备库可能是灾难

  • ⚠️ 依赖binlog开启(格式需为ROW)

  • ⚠️ binlog位点丢失需重新全量

  • ⚠️ 技术复杂度高,故障排查困难

前置检查

 -- 1. 检查binlog是否开启
SHOW VARIABLES LIKE 'log_bin';  -- 需返回: ON

 -- 2. 检查binlog格式
SHOW VARIABLES LIKE 'binlog_format';  -- 需返回: ROW

 -- 3. 检查binlog保留时长
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';  -- 建议≥7天

方案二:时间戳增量 + MERGE删除(批量方案)

工作原理

WITH current_keys AS (
 SELECT key1, key2 FROM jdbc.GaussDB连接信息.schema.table where update_time <= 上次更新最大值
)
MERGE INTO iceberg_catalog.db.MV1 t
USING current_keys s
ON t.key1 = s.key1 AND t.key2 = s.key2
WHEN NOT MATCHED BY SOURCE THEN DELETE

优势

  • ✅ 简单可控,无需binlog

  • ✅ 可按需调整同步频率

  • ✅ 失败可重跑,易于恢复

  • ✅ 支持删除(通过全量对比)

  • ✅ 适合T+1场景

限制

  • ⚠️ 删除识别依赖周期性全量对比

  • ⚠️ 需要lastUpdated字段准确(删除时也更新)

  • ⚠️ 历史回溯需扫描较大时间窗口

  • ⚠️ 对备库有查询压力


三、实战案例

案例:订单明细增量同步

表结构

订单明细表 (order_details)
- order_id        -- 订单ID(主键1)
- product_id      -- 商品ID(主键2)
- quantity        -- 数量
- amount          -- 金额
- lastUpdated     -- 最后更新时间

实施步骤

步骤1:增量数据同步

-- 查询增量数据(新增/更新)
INSERT INTO iceberg.dw.order_details_mv
SELECT 
  order_id,
  product_id,
  quantity,
  amount,
  lastUpdated
FROM jdbc.mysql_backup.ods.order_details
WHERE lastUpdated > '${last_sync_time}'  -- 上次同步时间
ON CONFLICT (order_id, product_id) 
DO UPDATE SET 
  quantity = EXCLUDED.quantity,
  amount = EXCLUDED.amount,
  lastUpdated = EXCLUDED.lastUpdated;

步骤2:清理删除数据(每日执行)

-- 获取源表当前所有主键
WITH current_keys AS (
  SELECT 
    order_id,
    product_id
  FROM jdbc.mysql_backup.ods.order_details
  WHERE lastUpdated <= CURRENT_TIMESTAMP
)

-- 删除目标表中源表已不存在的记录
MERGE INTO iceberg.dw.order_details_mv t
USING current_keys s
ON t.order_id = s.order_id 
   AND t.product_id = s.product_id
WHEN NOT MATCHED BY SOURCE THEN DELETE;

执行效果

  • 新增订单:自动插入

  • 修改订单:更新existing记录

  • 删除订单:定期清理(T+1延迟)


四、决策建议

决策树

Q1: binlog是否可用?
├─ NO → 方案二
└─ YES → Q2

Q2: 备库能否承受全量扫描?
├─ NO → 方案二(或等性能修复)
└─ YES → Q3

Q3: 是否需要实时同步?
├─ YES → 方案一
└─ NO (T+1可接受) → 方案二

Q4: 删除是否高频?
├─ 高频 → 方案一
└─ 低频 → 方案二

推荐策略

当前场景(备库性能差 + T+1需求) → 优先选择方案二

理由

  1. 避免首次全量对备库造成冲击

  2. T+1需求下,批量同步足够

  3. 简单可控,故障易恢复

长期规划(备库性能修复后) → 评估升级到方案一

条件

  • 删除频繁或需要实时性

  • 基础设施稳定

  • 团队具备CDC运维能力


五、关键注意事项

  1. lastUpdated字段准确性:必须确保删除操作也会更新此字段,否则无法识别删除

  2. 增量窗口设计:避免过大窗口(如3个月)导致扫描压力

  3. 删除延迟:方案二的删除有T+1延迟,需业务容忍

  4. 监控告警:同步延迟、失败率、数据一致性校验

  5. 分批执行:大表全量对比应分批进行,避免长事务