OceanBase 内存数据转储、合并说明
OceanBase 是“磁盘为主、内存加速”的分布式关系数据库,并非“纯内存数据库”。它把数据按 MemTable(内存)+ SSTable(磁盘) 两级存储:
写操作先写 MemTable 并同步写 Redo(Clog,类似 binlog),事务提交即持久化到 Clog,用户即可读到最新数据;
当 MemTable 大到一定阈值,或触发后台调度,才把内存数据 转储(minor freeze) 或 合并(major merge) 成新的磁盘 SSTable。
因此“落盘”分两种:
转储(小合并,minor merge / mini merge):只把 MemTable 刷成新的 Mini SSTable,不整库重合并,资源消耗小,频率高。
合并(大合并,major merge):把 Mini/Mini+Minor+Major SSTable 做全局归并,生成全新的 Major SSTable,并清理删除/过期数据,资源消耗大,默认每日 02:00 一次,也可手动/自动触发。
一、触发合并的几种情况
大合并(major merge)
a) 到达“合并调度时间窗”(默认每日 02:00,由 zone_merge_scheduler 控制)。
b) 手动命令:ALTER SYSTEM MAJOR FREEZE;
c) 副本在线迁移、Rebuild、恢复后补数据,需要先做一轮 major merge 才能提供服务。
d) 全局快照 GC、回收多版本数据、合并副本校验差量等内部任务。小合并/转储(minor/mini freeze)
a) MemTable 内存使用达到 memstore_limit_percentage(默认 50%)触发“活跃租户自动转储”。
b) Clog 回放限速、磁盘水位高、IO 压力大时,后台主动做 mini freeze 释放内存。
c) 手动命令:ALTER SYSTEM MINOR FREEZE [tenant=xxx];
二、一条 INSERT 会不会触发合并?
不会。
插入只写 MemTable + Clog,事务提交成功即返回客户端;
只有当 MemTable 大小达到阈值,后台才会把该 MemTable 转储成 Mini SSTable(小合并),对用户透明;
更不会直接触发“大合并”。
三、事务与“落盘”“binlog”的关系
OceanBase 没有 MySQL 的 binlog,而是 Clog(Redo)。
流程:
执行 INSERT → 写 MemTable;
事务提交时,对应的 Redo 日志(Clog)同步复制到多数派副本并刷盘;
一旦 Clog 落盘成功,事务就 真正提交,即使 MemTable 尚未转储,数据也绝不会丢;
后续 MemTable 转储/合并只是 把内存数据变成更紧凑的磁盘格式,不影响已经提交的事务持久性。
大合并,影响有多大、能不能让用户 SQL 明显抖动,取决于下面 5 个因素:
轮转合并是否开启(enable_merge_by_turn)
租户级合并线程数、I/O 带宽限速
业务高峰还是低峰
列存/行存、分区数量、数据量
硬件余量(CPU、磁盘 IOPS)
四、大合并默认行为与资源开销
4.x 版本以后大合并全部“按租户、按 Zone 顺序”串行执行;单个租户内部再按 tablet 并行。
默认给每个租户 6 个 compaction 线程,1 块盘 10 MB/s 量级限速;对 32C/64G 规格节点,合并时 CPU 会抬高 15-25%,I/O 读写 100-200 MB/s,持续 0.5-2 h(TB 级数据)[1][13]。
如果分区数特别多(≥10 万)或用了列存,归并时要“行→列”再编码,耗时可能拉到数小时甚至 10 h+,资源曲线会被进一步拉高[13]。
五、对在线业务的影响路径
CPU 被合并线程吃掉 → SQL rt 抖动
携程在春晚活动前关掉轮转合并,结果 3 个 Zone 并发合并,CPU 打到 90%,MySQL 业务 QPS 跌 30%,rt 涨 3 倍;后来把 enable_merge_by_turn 打开,并调低 compaction_low_thread_score=3,rt 回落到 1.2 倍[11]。I/O 带宽打满 → 查询、Clog 刷盘慢
某社区用户 SSD 盘持续 100 % util,MySQL 只读查询 rt 从 5 ms 涨到 60 ms;在 ob_compaction_io_bandwidth_limit 里把合并读/写分别限速 60 MB/s 后,rt 恢复[2]。切 Leader(轮转合并的副作用)
默认“先切走 Leader→合并→切回”,切主 3-5 s 期间连接会断;对长连接 MySQL 业务基本无感,但对短连接、连接池较小的应用会出现“抖动 30-60 s”[11]。
六、4 个现网可落地的“稳合并”策略
时间窗 + 轮转合并
把 major_freeze_duty_time 设在 02:00-05:00;enable_merge_by_turn=true;高峰期(08-24 点)自动 block merge。资源节流
compaction_low_thread_score = 3(默认 6)
ob_compaction_io_bandwidth_limit = ‘200M’
这样 CPU 峰值压到 10-15%,磁盘 util < 50 %。列存/大分区场景提前拆任务
4.x 支持水平+垂直并行,可手动调大
alter system set _ob_compaction_column_group_count=8;
把 12 h 合并压到 3 h 以内[13]。监控 + 熔断
对 MySQL 业务 rt、p99、error 做实时看板;合并一旦触发 rt>2×基线或错误率>1 %,立即
alter system suspend merge;
待资源回落后再 resume merge,官方文档给出过“合并超 24 h 先 suspend 再排查”的应急流程[3]。
结论
只要打开轮转合并、给合并线程/IO 加限速、并把时间窗放在业务低峰,大合并对正常 MySQL 业务可以做到“无感知”——CPU ±5 %、rt +10 % 以内。
反之,如果并发合并、不限速又赶上高峰,CPU、IO 双高,MySQL 查询 rt 翻倍甚至掉 QPS 是很常见的。通过上面 4 组参数+监控,现网已能把“合并风险”降到和 MySQL 夜间批量差不多水平。
