首批通过分布式安全可靠测评,为关键业务系统打造
合并
更新时间:2026-04-10 11:58:01
与转储相比,合并通常是一个比较重要的操作,时间也相对较长,在最佳实践中,一般期望在一天只做一次合并操作,并且控制在业务低峰期进行,因此有时也会把合并称为每日合并。
合并操作(Major Compaction)是将动静态数据做归并,会比较费时。当转储产生的增量数据积累到一定程度时,通过 Major Freeze 实现大版本的合并。它和转储最大区别在于,合并是租户在一个统一的快照点与其对应的静态数据进行合并的行为,最终会形成一个租户级快照。
| 转储(Mini Compaction) | 转储(Minor Compaction) | 合并(Major Compaction) |
|---|---|---|
| 分区或租户级别,只是 MemTable 的物化 | 分区级别 | 租户级别,产生一个租户级快照 |
| 每个 OBServer 节点的每个租户独立决定自己 MemTable 的冻结操作,主备分区不保持一致 | 每个分区根据当前 SSTable(包含 Mini SSTable 和 Minor SSTable) 的数量来执行分区内的 Minor Compaction | 租户所有分区一起做 MemTable 的冻结操作,要求主备分区保持一致,在合并时会对数据进行一致性校验。 |
| 可能包含多个不同版本的数据行 | 可能包含多个不同版本的数据行 | 只包含快照点的版本行 |
| 将一个或多个 MemTable 持久化为 Mini SSTable | 将多个 Mini SSTable 合成一个 Mini SSTable,或者将多个 Mini SSTable 与一个 Minor SSTable 合并产生一个新的 Minor SSTable,仅包含增量数据,最终被删除的行需要特殊标记。 | 合并会把当前大版本的 SSTable 和 MemTable 与前一个大版本的全量静态数据进行合并,产生新的全量数据。 |
合并虽然比较费时, 但是同时为数据库提供了一个操作窗口,在这个窗口内 OceanBase 数据库可以利用合并特征完成多个计算密集任务, 提升整体资源利用效率。
数据压缩
合并期间 OceanBase 数据库会对数据进行两层压缩,第一层是数据库内部基于语义的编码压缩,第二层是基于用户指定压缩算法的通用压缩,使用 lz4 等压缩算法对编码后的数据再做一次瘦身。压缩不仅仅节省了存储空间,同时也会极大地提升查询性能。目前 OceanBase 数据库支持(snappy、lz4、lzo,zstd)等压缩算法,允许用户在压缩率和解压缩时间上做各自的权衡。MySQL 和 Oracle 在一定程度上也支持对数据的压缩,但和 OceanBase 相比,由于传统数据库定长页的设计,压缩不可避免的会造成存储的空洞,压缩效率会受影响。而更重要的是,对于 OceanBase 数据库这样的 LSM-Tree 架构的存储系统,压缩对数据写入性能是几乎无影响的。
数据校验
通过租户级一致快照进行合并能够帮助 OceanBase 数据库很容易的进行多副本的数据一致校验, 合并完成后多个副本可以直接比对基线数据来确保业务数据在不同副本间是一致的。另一方面还能基于这个快照基线数据做主表和索引表的数据校验,保障数据在主表和索引表之间是一致的。
Schema 变更
对于加列、减列等 Schema 变更,OceanBase 数据库可以在合并中一起完成数据变更操作,DDL 操作对业务来说更加平滑。
合并方式
合并有很多种不同的方式,具体的描述如下。
全量合并
全量合并是 OceanBase 数据库最初的合并算法,和 HBase 与 RocksDB 的 major compaction 过程是类似的。在全量合并过程中,会把当前的静态数据都读取出来,和内存中的动态数据合并后,再写到磁盘上去作为新的静态数据。在这个过程中,会把所有数据都重写一遍。全量合并会极大的耗费磁盘 IO 和空间,除了 DBA 强制指定外,目前 OceanBase 数据库一般不会主动做全量合并。
增量合并
在 OceanBase 数据库的存储引擎中,宏块是 OceanBase 数据库基本的 IO 写入单位,在很多情况下,并不是所有的宏块都会被修改,当一个宏块没有增量修改时,合并可以直接重用这个数据宏块, OceanBase 数据库中将这种合并方式称之为增量合并。增量合并极大地减少了合并的工作量,是OceanBase 数据库目前默认的合并算法。更进一步地,OceanBase 数据库会在宏块内部将数据拆分为更小的微块,很多情况下,也并不是所有的微块都会被修改,可以重用微块而不是重写微块。微块级增量合并进一步减少了合并的时间。
渐进合并
为了支持业务的快速发展,用户不可避免地要做加列、减列、建索引等诸多 DDL 变更。这些 DDL 变更对于数据库来说通常是很昂贵的操作。MySQL 在很长一段时间内都不能支持在线的 DDL 变更(直到 5.6 版本才开始对 Online DDL 有比较好的支持),而即使到今天,对于 DBA 来说,在 MySQL 5.7 中做 Online DDL 仍然是一件比较有风险的操作,因为一个大的 DDL 变更就会导致 MySQL 主备间的 replication lag。
OceanBase 数据库在设计之初就考虑到了 Online DDL 的需求,目前在 OceanBase 数据库中加列、减列、建索引等 DDL 操作都是不阻塞读写的,也不会影响到多副本间的 paxos 同步。加减列的 DDL 变更是实时生效的,将对存储数据的变更延后到每日合并的时候来做。然而对于某些 DDL 操作如加减列等,是需要将所有数据重写一遍的,如果在一次每日合并过程中完成对所有数据的重写,那么对存储空间和合并时间都会是一个比较大的考验。为了解决这个问题,OceanBase 数据库引入了渐进合并,将 DDL 变更造成的数据重写分散到多次每日合并中去做,假设渐进轮次设置为 60,那么一次合并就只会重写 60 分之一的数据,在 60 轮合并过后,数据就被整体重写了一遍。渐进合并减轻了 DBA 做 DDL 操作的负担,同时也使得 DDL 变更更加平滑。
合并触发
合并触发有三种触发方式:自动触发、定时触发与手动触发。
当租户的 Minor Freeze 次数超过阈值时,就会自动触发该租户的合并。
也可以通过设置参数来在每天的业务低峰期定时触发合并。
obclient> ALTER SYSTEM SET major_freeze_duty_time = '02:00' TENANT = t1;也通过以下的运维命令手动触发合并。
系统租户发起其他租户的合并
对
sys租户发起的合并obclient> ALTER SYSTEM MAJOR FREEZE TENANT = sys;对所有用户租户发起的合并
obclient> ALTER SYSTEM MAJOR FREEZE TENANT = all_user;对所有 META 租户发起的合并
obclient> ALTER SYSTEM MAJOR FREEZE TENANT = all_meta;对租户 t1 和 t2 发起的合并
obclient> ALTER SYSTEM MAJOR FREEZE TENANT = t1,t2;
用户租户发起本租户的合并
obclient> ALTER SYSTEM MAJOR FREEZE;
相关文档
更多合并操作,请参见 合并。