分区表 DROP PARTITION
后数据真的消失了吗?
不是删除,是直接丢弃整个分区文件(
.ibd),MySQL 不走行级清理逻辑,也不写 binlog(除非开启
binlog_row_image=FULL且使用 ROW 格式)。这意味着:一旦执行
ALTER TABLE ... DROP PARTITION p2023,对应分区的物理文件被移出数据字典,InnoDB 层无法回滚,也无法通过
FLASHBACK恢复。
常见误操作场景包括:运维脚本未加
WHERE校验就批量删分区、误将
REORGANIZE PARTITION写成
DROP、或用
TRUNCATE PARTITION但没意识到它等价于
DROP + RECREATE。 确认是否真丢失:查
INFORMATION_SCHEMA.PARTITIONS,若
PARTITION_NAME已不存在,且
TABLE_ROWS = 0,基本无原地恢复可能 检查磁盘残留:
ls -l /var/lib/mysql/your_db/your_table#P#p2023.ibd,如果文件还在且未被
rm或覆盖,可尝试拷贝回原路径并执行
ALTER TABLE ... IMPORT PARTITION(仅限
innodb_file_per_table=ON且未执行过
DISCARD) 备份依赖:必须依赖最近一次全量 + 增量 binlog;若 binlog 被 purged 或格式为 STATEMENT,
mysqlbinlog无法还原分区级操作
REORGANIZE PARTITION
报错 ERROR 1503 (HY000)
怎么办?
这个错误本质是 MySQL 拒绝非法的分区边界调整,比如试图把一个 RANGE 分区拆成两个但新下界 > 原下界,或合并时边界不连续。它不是数据损坏,而是 DDL 语义校验失败。
典型触发条件:
源分区p_max(
VALUES LESS THAN MAXVALUE)参与
REORGANIZE—— 不允许,必须先
SPLIT出新分区再操作 新定义的
VALUES LESS THAN值小于等于前一分区的上界(如前一分区到
100,新分区却设
LESS THAN 90) HASH / KEY 分区试图改变
PARTITIONS数量的同时指定具体分区名(语法冲突)
修复动作不是“修数据”,而是修正 SQL:
ALTER TABLE logs REORGANIZE PARTITION p2023 INTO ( PARTITION p2023_q1 VALUES LESS THAN (20230401), PARTITION p2023_q2 VALUES LESS THAN (20230701) );
注意:该语句要求原
p2023的上界必须 ≥
20230701,否则报
ERROR 1503。
查询返回空或部分数据,但 EXPLAIN PARTITIONS
显示命中了分区
这往往不是分区失效,而是分区表达式与查询条件类型不匹配,导致 MySQL 无法做 partition pruning。最典型的是字符串日期字段(如
dt VARCHAR(8))建了 RANGE 分区,但查询用了
WHERE dt = '2023-01-01'—— 类型隐式转换让分区裁剪失效。
验证方式:
执行EXPLAIN PARTITIONS SELECT * FROM t WHERE dt = '20230101';,看
partitions列是否只列出了目标分区 若显示
ALL或多个分区,说明没裁剪;改用
WHERE dt >= '20230101' AND dt 强制范围匹配对
LIST分区,确保查询值严格等于某一个
VALUES IN中的项(不能是子查询结果或函数返回值)
另一个隐蔽原因是时区:若分区键是
TIMESTAMP,而会话时区(
time_zone)和系统时区不一致,
WHERE ts > '2023-01-01'可能跨分区计算出错。统一设为
+00:00可规避。
从非分区表迁移到分区表时数据丢失或重复
用
ALTER TABLE ... PARTITION BY ...在线重定义时,MySQL 会重建整表,但过程并非原子:若中途崩溃,可能留下半成品(
table_name#P#p1.ibd存在但数据字典未更新),或触发复制中断(尤其主从延迟高时)。
安全迁移必须分三步走:
先创建空分区表:CREATE TABLE t_part (...) PARTITION BY RANGE (dt) (...)用
INSERT INTO t_part SELECT * FROM t_orig;迁移,加
WHERE dt BETWEEN ...分批控制内存 最后原子切换:
RENAME TABLE t_orig TO t_orig_bak, t_part TO t_orig;
切忌直接
ALTER TABLE t_orig PARTITION BY ...—— 它在 5.7 中会锁表,在 8.0 中虽支持 ALGORITHM=INSTANT(仅限添加/删除分区),但重分区结构仍需 COPY。
真正容易被忽略的是:迁移后必须重新收集统计信息(
ANALYZE TABLE t_part),否则优化器可能因旧的非分区表统计值误判执行计划,导致慢查询看似“分区没生效”。
