误删分区表单个分区后无法回滚,必须依赖备份恢复;DROP PARTITION是DDL操作,不记录行级binlog事件,只能从全量或增量备份中按分区边界提取对应数据子集并导入。

误删分区表单个分区后,DROP PARTITION 无法回滚,必须依赖备份恢复
MySQL 的分区表不支持单个分区的原子级回滚,DROP PARTITION 是 DDL 操作,执行即生效,binlog 中仅记录语句(非行事件),无法用 mysqlbinlog 回放还原数据。所以“精准恢复单个分区”这件事,本质是:从全量或增量备份中,把该分区对应的数据子集抽出来,再导入。
确认被删分区的边界值和存储引擎类型,决定提取方式
恢复的前提是知道该分区实际覆盖哪些数据——不是看 PARTITION BY RANGE 的定义,而是查删除前的 INFORMATION_SCHEMA.PARTITIONS 或备份时的 SHOW CREATE TABLE 输出。尤其注意:
-
MyISAM分区表每个分区对应独立.MYD/.MYI文件,若备份是文件级(如rsync或Percona XtraBackup全备),可直接从备份目录里按分区名(如tbl001#P#p202309)拷出对应文件,替换到现库数据目录后FLUSH TABLES -
InnoDB分区表所有分区共用一个表空间(除非启用了innodb_file_per_table=ON且是 MySQL 5.7.6+ 的ALGORITHM=INSTANT分区),此时无法按文件提取,必须走逻辑导出 - 若使用
mysqldump全备,需结合--where条件过滤出目标分区的数据,例如原分区为RANGE COLUMNS(dt) VALUES LESS THAN ('2023-10-01'),则导出时加--where="dt >= '2023-09-01' AND dt
用 mysqlpump 或 mysqldump 配合 --where 精准导出分区数据
mysqlpump(MySQL 5.7+)比 mysqldump 更适合分区表,它支持 --include-tables 和 --where 组合,且默认并行导出。但要注意:
-
--where必须与分区键类型严格一致:日期字段不能写成字符串比较(如'2023-09'),而要用DATE()或范围表达式;枚举/列表分区需匹配具体值,例如--where="region IN ('CN','JP')" - 导出时加上
--skip-triggers --skip-events --no-create-info,避免结构或逻辑干扰,只取数据 - 导入前先用
ALTER TABLE ... ADD PARTITION把分区结构补回来,否则INSERT会因分区不存在而失败;语句需完全复刻原SHOW CREATE TABLE中该分区的定义 - 导入建议用
mysql --force,跳过重复主键或唯一键冲突(如果备份时间点后已有新数据写入该分区范围)
恢复后验证分区数据量和边界一致性,别只看行数
即使 SELECT COUNT(*) 对得上,也不代表数据正确——分区键值越界、时区转换错误、字符集隐式转换都可能导致部分行被路由到其他分区。务必做这几件事:
- 查
SELECT MIN(dt), MAX(dt) FROM tbl PARTITION(p202309),确认极值在预期范围内 - 对比备份时刻该分区的
CHECKSUM TABLE tbl PARTITION(p202309)值(如果当时算过) - 抽样几条边界数据(如
dt = '2023-09-01'和'2023-09-30')跟备份库中原始记录逐字段比对 - 检查
INFORMATION_SCHEMA.PARTITIONS中该分区的TABLE_ROWS是否非零,且DATA_LENGTH明显大于空分区
最易被忽略的是:恢复用的 --where 条件是否受 SQL mode(如 STRICT_TRANS_TABLES)或默认时区影响,导致边界行丢失。动手前,先在测试库用同样条件 SELECT 一把,数一数、看一看。


















