OceanBase 根据时间自动新增表分区
适用对象:OceanBase MySQL 兼容模式,按
created_at使用RANGE COLUMNS分区的订单表。本文介绍自动维护方案,不是可直接运行的生产脚本。目标 OceanBase 的版本、原生自动分区能力及分区拆分语法尚未核验,实施前必须按实际版本确认并测试。
1. 需求与结论
希望订单按创建月份存放,业务增长到新月份时,系统自动准备对应分区,应用始终读写同一张逻辑表 orders。
可以通过定时任务自动维护月份分区,但普通 RANGE COLUMNS(created_at) 定义本身不会随时间自动创建新分区。
| 行为 | 普通 RANGE 分区表是否自动完成 |
|---|---|
根据 created_at 把记录路由到已有分区 |
是 |
| 月份变化时创建新分区 | 否,需要额外能力或维护任务 |
| 把兜底分区中的数据主动拆成月份分区 | 否,需要执行受支持的分区变更 |
| 新增分区后让查询仍使用原表名 | 是,应用仍访问逻辑表 |
是否可以使用数据库原生自动分区能力,应按实际 OceanBase 版本、兼容模式及限制核验。本文默认采用外部定时任务,不假定存在可直接使用的 interval 分区语法或兼容的数据库事件调度功能。
2. 当前表结构与边界
示例初始表:
sql
CREATE TABLE orders (
id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
amount DECIMAL(18, 2) NOT NULL,
status TINYINT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL,
PRIMARY KEY (created_at, id)
)
PARTITION BY RANGE COLUMNS (created_at) (
PARTITION p_before_202609
VALUES LESS THAN ('2026-09-01'),
PARTITION p202609
VALUES LESS THAN ('2026-10-01'),
PARTITION p202610
VALUES LESS THAN ('2026-11-01'),
PARTITION p_future
VALUES LESS THAN (MAXVALUE)
);
这是一张逻辑表、四个分区。该 SQL 仅说明初始设计,已有表不要重复创建。
| 分区 | 时间范围 |
|---|---|
p_before_202609 |
小于 2026-09-01 00:00:00 |
p202609 |
[2026-09-01, 2026-10-01) |
p202610 |
[2026-10-01, 2026-11-01) |
p_future |
[2026-11-01, 无限未来) |
[开始, 结束) 表示包含开始、不包含结束。分区名称只用于标识,真正决定路由的是边界。
注意:示例中的 id 由应用提供,复合主键只保证 (created_at, id) 唯一,不单独保证 ID 全表唯一。自动维护分区不应顺便修改这一业务约束。
3. 推荐方案:每日检查,提前维护三个月
使用应用任务、独立运维脚本或现有任务平台,每天按业务时区执行一次,确保当前月及未来三个完整自然月都有独立分区。
例如,当前为 2026 年 12 月,目标是覆盖:
text
2026 年 12 月: [2026-12-01, 2027-01-01)
2027 年 1 月: [2027-01-01, 2027-02-01)
2027 年 2 月: [2027-02-01, 2027-03-01)
2027 年 3 月: [2027-03-01, 2027-04-01)
剩余未来时间: [2027-04-01, 无限未来)
相应目标上界为当前月月初加四个自然月,不是简单加固定天数。每天检查而不是每月只运行一次,可以给任务失败后的重试和人工处理留出时间。
任务首次接管前,应人工核对当前表结构并完成必要的历史边界初始化。常规任务只负责向未来扩展,不自动改造任意历史分区。
4. 如何处理已有的 p_future
4.1 不能在 MAXVALUE 后直接追加月份
已有兜底分区覆盖全部未来范围,不能直接在它后面增加一个有限上界的月份分区。需要使用目标版本支持的拆分、重组或其他经过验证的变更方式。
以初始结构为例,要连续准备到 2027 年 3 月,目标是把原 p_future 拆成:
text
原 p_future:[2026-11-01, 无限未来)
↓
p202611:[2026-11-01, 2026-12-01)
p202612:[2026-12-01, 2027-01-01)
p202701:[2027-01-01, 2027-02-01)
p202702:[2027-02-01, 2027-03-01)
p202703:[2027-03-01, 2027-04-01)
p_future:[2027-04-01, 无限未来)
不能只创建一个名为 p202701、上界为 2027-02-01 的分区,就认为它只保存 1 月数据。如果前一个上界仍是 2026-11-01,它实际包含 11 月、12 月和 1 月。
4.2 已有数据会如何处理?
在版本支持相应操作且变更成功的前提下,数据库会按新边界组织原兜底范围的数据:
| 原有记录 | 新归属 |
|---|---|
2026-12-15 10:00:00 |
p202612 |
2027-01-15 10:00:00 |
p202701 |
2027-05-15 10:00:00 |
新的 p_future |
数据处理可能带来重写、索引维护和空间开销。提前维护可减少正常业务下兜底数据的积累,但不能保证它为空,因为可能已有未来日期的记录。
严禁用"删除 p_future,再创建新分区"替代拆分,删除分区可能直接删除其中的数据。
4.3 版本不支持拆分怎么办?
暂停自动变更并告警,评估升级、调整维护策略或新表迁移。新表迁移必须单独设计全量复制、增量衔接、校验、切换和回退,不能由定时任务自动临时发起。
本文不提供未经验证的 REORGANIZE PARTITION 或 SPLIT PARTITION 可执行语句。MySQL 与不同 OceanBase 版本的支持情况不能混用。
5. 自动维护任务流程
text
定时触发
↓
确认目标集群、租户、数据库和表
↓
获取该表的维护锁
↓
重新读取分区元数据,检查是否有未结束的变更
↓
按业务时区计算当前月和目标覆盖上界
↓
检查真实边界是否符合已批准的月度布局
├── 不符合 → 停止并告警,人工核对
└── 符合
↓
计算缺少的连续月份边界
├── 无缺失 → 记录成功检查,结束
└── 有缺失
↓
检查资源和已批准的变更条件
↓
执行经版本验证的分区维护操作
↓
核验服务端完成状态及新边界
↓
记录结果,释放维护锁
实现要求:
- 按边界判断,而不是只看分区名。 同名分区的范围可能不是预期月份;存在冲突时停止,不自动删除或覆盖。
- 幂等。 同一任务重复运行时,已正确存在的边界不重复创建。
- 单表串行。 多实例任务共用维护锁,并避免与人工 DDL 并行;长操作需保证锁所有权有效。
- 异常后先对账。 超时、断连或进程重启后,先检查服务端任务和实际结构,再决定是否重试。
- 有限重试。 只对确认可重试且状态明确的失败重试;不支持的语法、布局异常和资源不足应告警。
- 结构化处理元数据。 按目标版本的元数据格式规范化日期边界,不对完整建表 SQL 做脆弱的字符串替换。
- 限制权限与输入。 使用获准的专用维护账号、固定表白名单和受控标识符,不接受任意用户输入拼接 DDL。
不得在每次订单 INSERT 前尝试创建分区,不得让业务写入请求同步等待分区维护任务。
6. 版本核验与只读检查
在目标业务租户和数据库中检查:
sql
SELECT VERSION();
SELECT DATABASE();
SHOW CREATE TABLE orders;
SELECT
PARTITION_NAME,
PARTITION_ORDINAL_POSITION,
PARTITION_METHOD,
PARTITION_EXPRESSION,
PARTITION_DESCRIPTION
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'orders'
ORDER BY PARTITION_ORDINAL_POSITION;
结合部署信息确认完整 OceanBase 版本,不只根据 MySQL 兼容版本号判断能力。还应核对:
- 是否支持对现有 RANGE 分区执行所需拆分或重组,以及准确的语法。
- 全局索引、唯一约束、外键或其他对象是否限制操作。
- 在线执行、并发 DML、锁、超时、任务查询和取消行为。
- 分区数量上限及长期增长影响。
- 额外磁盘、日志、CPU、I/O 需求和副本健康前提。
测试通过后再将准确 DDL 固化到版本对应的维护实现中,不在生产通过反复尝试语法来探测能力。
7. 保留与不保留兜底分区的取舍
| 方案 | 优点 | 风险 |
|---|---|---|
保留 MAXVALUE |
维护任务短暂失败时,未来时间通常仍有分区可以接收 | 需要支持兜底拆分;任务长期失败可能悄悄积累大量数据 |
不设 MAXVALUE,提前追加月份 |
在支持追加的版本中,维护方式通常更直接 | 超出最大边界的数据写入会失败,维护可靠性要求更高 |
本文基于已有 p_future,默认保留兜底并核验拆分能力。是否取消兜底应作为独立结构变更评估,不能直接删除已有分区。
8. 时间与业务规则
DATETIME不携带时区,应统一应用写入和任务计算边界的时间口径。默认采用业务约定的时区,不依赖任务主机的隐含时区。- 使用自然月月初计算边界,正确处理跨年、闰年和不同月份长度。
- 分区路由依据记录的
created_at,不是 INSERT 实际发生的月份;历史补写会进入相应历史范围。 - 初始
p_before_202609继续保留历史汇总范围,普通任务不自动把它拆成历史月份。 - 对异常未来时间由业务明确校验规则,不应为单条异常记录无限扩展分区。
- 更新
created_at可能涉及跨分区移动,需按版本验证;订单创建时间通常宜保持稳定。 - 自动创建和历史清理分开设计。默认不自动删除历史分区,归档与删除需独立授权和恢复方案。
9. 监控、告警与验收
9.1 监控项目
- 最近成功检查时间、最近成功变更时间、连续失败次数及错误原因。
- 已建立的独立月份分区覆盖上界,与目标上界的差距。
p_future中的数据积累趋势;采用版本支持的低成本统计或监控手段,避免每日全表精确计数。- DDL 耗时、租户 CPU、内存、磁盘余量、日志和业务延迟。
- 分区总数与版本上限之间的余量。
不能把 MAXVALUE 当作"已提前创建所有月份":监控应观察兜底前的实际月份边界。
9.2 测试与验收
- 空表、已有月份数据及兜底中已有数据的场景均测试通过。
- 月初边界、跨年、闰年和历史补写路由正确。
- 同一任务反复运行不重复修改,多个任务竞争时只有一个执行变更。
- DDL 超时、断连、进程重启后能够核对状态,不盲目重复提交。
- 分区名称冲突、非月初边界或布局异常时停止并告警。
- 核对变更前后的字段、约束、数据和核心查询性能。
- 并发写入期间的校验使用明确一致性边界,不把两次独立 COUNT 的差异直接当成丢数据。
- 已验证备份恢复和人工接管流程,未引入自动删除历史数据的行为。
10. 推荐默认配置与总结
| 配置项 | 默认建议 |
|---|---|
| 执行频率 | 每天一次,安排在业务低峰 |
| 时间口径 | 明确配置的业务时区,与 created_at 写入口径一致 |
| 提前范围 | 当前月及未来三个完整自然月 |
| 分区命名 | pYYYYMM,但以真实边界为准 |
| 兜底策略 | 保留现有 p_future,先验证目标版本拆分能力 |
| 历史处理 | 不自动删除,不自动重整历史汇总分区 |
| 并发控制 | 单表维护锁,变更后重新核对元数据 |
| 异常策略 | 状态核验、有限重试、告警与人工接管 |
自动化的核心是提前维护分区边界,而不是让 INSERT 临时触发建分区。对于已有 MAXVALUE 的表,先确认版本支持如何安全拆分兜底范围,再将经过测试的操作交给定时任务执行。
官方资料入口:https://www.oceanbase.com/docs。请选择实际部署版本,查阅 MySQL 模式的分区管理、ALTER TABLE 限制、在线 DDL、索引约束和任务监控说明。