如何用 TRUNCATE PARTITION 实现分区表分区清空不锁表

10次阅读

TRUNCATE PARTITION 不能完全避免锁表,但仅对目标分区加 MDL_WRITE 锁,不影响其他分区及 DML;仅支持 RANGE、LIST、COLUMNS 分区,不支持 HASH 和 KEY;需检查分区名大小写、事务占用及 mysql 版本(8.0.23+ 才支持二级分区)。

如何用 TRUNCATE PARTITION 实现分区表分区清空不锁表

TRUNCATE PARTITION 能否真正避免锁表?

不能完全避免,但锁的粒度大幅降低——TRUNCATE PARTITION 只对目标分区加 MDL_WRITE 元数据锁(而非整表 MDL_EXCLUSIVE),其他分区和 DML 操作基本不受影响。前提是:表使用 innodb_file_per_table=ON,且分区是 INNODB 引擎。

哪些分区类型支持 TRUNCATE PARTITION?

仅支持 RANGELISTCOLUMNS 分区;HASHKEY 分区不支持该语法,执行会报错:Error 1735 (HY000): Unknown partition 'p0' in table 't'(即使分区存在)。可通过 select PARTITION_NAME FROM INforMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t' 确认分区类型。

执行前必须检查的三项配置

  • SQL_LOG_BIN=OFF 不是必须项,但若在主库执行且 binlog_format=ROW,TRUNCATE PARTITION 会被记录为单条事件,从库回放时仍走分区级清空逻辑——这点比 delete 更安全
  • 确认分区名拼写严格匹配(区分大小写,取决于 lower_case_table_names 设置),错误示例:TRUNCATE PARTITION p202401 实际分区名为 P202401
  • 检查该分区是否被显式引用在未提交事务中(如 SELECT ... FROM t PARTITION(p202401) FOR UPDATE),否则会阻塞直到事务结束

替代方案对比:TRUNCATE PARTITION vs DROP + READD PARTITION

某些场景下(如需重置自增 ID 或释放磁盘空间更彻底),可考虑 ALTER TABLE t DROP PARTITION p202401, ADD PARTITION (...)。但注意:DROP PARTITION 会重建分区结构,耗时更长,且期间对该分区的 DML 会被阻塞;而 TRUNCATE PARTITION 是原子操作,速度更快、影响窗口更短。

最易被忽略的一点:MySQL 8.0.23+ 才支持对二级分区(SUBPARTITION)单独 TRUNCATE;低版本只能清空整个一级分区,哪怕你只想清理其中某个子分区。

text=ZqhQzanResources