mysql 5.7+ 和 mariadb 中 add partition 无法直接追加到含 values less than (maxvalue) 的末尾分区,必须先用 reorganize partition 将其拆分为新分区和新的 maxvalue 分区,且新分区须在前、maxvalue 在后。
alter table add partition 语法写错就直接报错
mysql 5.7+ 和 mariadb 支持 range/list 分区表的在线加分区,但 add partition 对已有 maxvalue 分区非常敏感——只要目标表末尾是 values less than (maxvalue),你就不能直接追加新分区,否则报错:error 1503 (hy000): a primary key must include all columns in the table's partitioning function 或更常见的 error 1481 (hy000): invalid partition name,其实根本原因不是名字问题,而是语义冲突。
实操建议:
- 先用
SHOW CREATE TABLE tbl_name确认当前最后分区是否为VALUES LESS THAN (MAXVALUE) - 如果存在,必须先用
REORGANIZE PARTITION把它拆开,再往里塞新分区 -
ADD PARTITION只能用于末尾没有MAXVALUE的情况;一旦有,它就失效 - 不要试图用
ALTER TABLE ... ADD PARTITION (PARTITION p_new VALUES LESS THAN (MAXVALUE))覆盖旧的 MAXVALUE 分区——语法合法但会报错,MySQL 不允许重复定义MAXVALUE
用 REORGANIZE 替换 MAXVALUE 分区才能继续加
这是最常卡住的一步:你想按月加一个 p202404,但表末尾是 p_max VALUES LESS THAN (MAXVALUE)。此时必须把它“切开”,腾出位置。
实操建议:
- 假设原分区是
PARTITION p_max VALUES LESS THAN (MAXVALUE),你想加p202404 VALUES LESS THAN (20240401),那得这样重组织:ALTER TABLE tbl_name REORGANIZE PARTITION p_max INTO ( PARTITION p202404 VALUES LESS THAN (20240401), PARTITION p_max VALUES LESS THAN (MAXVALUE) );
- 注意顺序:新分区必须在前,
MAXVALUE分区必须在后,否则 MySQL 拒绝执行 - 该操作会锁表(非元数据锁),大表慎用;MariaDB 10.3+ 支持
ALGORITHM=INPLACE,但 MySQL 8.0 仍需 copy(除非是 NDB 引擎) - 数值型分区列(如
TO_DAYS(date_col))要确保新边界值类型匹配,别传字符串进去
日期字段分区时,MAXVALUE 的边界容易算错
用 TO_DAYS()、YEAR() 或直接 DATE 列做分区键时,MAXVALUE 看似兜底,实则隐藏陷阱:它不接受任何比当前最大值小的数据,但你新加的分区如果边界值 MAXVALUE 分区。
实操建议:
- 查清当前最大数据时间:
SELECT MAX(dt) FROM tbl_name,再决定新分区上限——比如最大是'2024-03-31',那p202404应设为VALUES LESS THAN ('2024-04-01'),不是'2024-04-30' - 用
TO_DAYS('2024-04-01')算出整数再填进LESS THAN,避免隐式转换出错 - 千万别写
VALUES LESS THAN (TO_DAYS('2024-04-01'))在 DDL 里——MySQL 不支持函数调用,只接受字面量整数或MAXVALUE - 测试时用
EXPLAIN PARTITIONS SELECT * FROM tbl_name WHERE dt = '2024-04-05'确认命中预期分区
分区键含主键/唯一索引时,ADD PARTITION 会额外校验
如果表有主键或唯一索引,且分区键没包含全部索引列,ADD PARTITION 会直接拒绝,报错信息里带 PRIMARY KEY must include all columns in the table's partitioning function。这不是语法错,是设计约束。
实操建议:
- 检查分区键是否已覆盖所有主键列(
SHOW CREATE TABLE最后一行会标出PARTITION BY ... (col1, col2)) - 如果主键是
(id, dt),但只按dt分区,就必须改成PARTITION BY RANGE (TO_DAYS(dt))并确保id不参与分区函数——不行,得把id加进函数或改主键结构 - 常见解法:把主键改成
(dt, id),让分区键dt成为主键前缀;否则只能放弃该表的分区,或用子分区绕过 - 这个限制在添加任何分区(包括首次
ADD)时都生效,不是仅限于处理MAXVALUE
真正麻烦的从来不是语法怎么写,而是你得先判断当前分区结构是否允许加——尤其当别人建的表、文档缺失、又没注释时,SHOW CREATE TABLE 和 SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS 得翻两遍才敢动。










