首页/数据/SQL 速查/DELETE 基础与分批删除
变更与事务52 条

DELETE 基础与分批删除

按条件删除行:逐行记录日志、可回滚、触发 DELETE 触发器;大表删除要分批做,避免长事务与主从延迟。

SQL 速查数据更新于 2026-10-13

DELETE 是什么

DELETE 按条件删除行,逐行记录日志、可回滚、会触发 DELETE 触发器与级联外键动作。MySQL 单表 DELETE 支持 ORDER BY 与 LIMIT,多表语法不支持 LIMIT;PostgreSQL 用 USING 或子查询删除关联表的数据。大表删除必须分批做:一次性删掉上千万行会长时间持锁、产生大量 binlog 或 WAL,主从延迟直线上升。清空整表用 TRUNCATE 更快,但它不逐行记日志、不可回滚,还会重置自增值。

基本信息

作用按条件删除行,可回滚,会触发触发器与级联动作
MySQL 分批写法DELETE FROM t WHERE … ORDER BY id LIMIT 1000
PostgreSQL 关联删除WHERE id IN (SELECT …) 或 USING 子句
清空整表TRUNCATE 更快,但不逐行记日志、不可回滚、重置自增值
空间回收删除行不会立刻归还磁盘,需要后续重建表或碎片整理
生产替代方案常用软删除标记 is_deleted 代替物理删除

典型使用场景

  • 清理历史数据:按时间分批删除过期日志与流水
  • 撤销操作产生的冗余行:按业务主键精确删除
  • 数据修正:删除导入错误造成的重复行
  • 归档前置动作:先复制到归档表,再删除原表数据
  • 清理孤儿数据:删除没有对应主表的明细行
  • 测试环境重置:清空业务表,注意 TRUNCATE 与自增值的关系

分批删除与关联删除

分批删除与关联删除
-- MySQL:分批删除,避免长事务与主从延迟
DELETE FROM logs
WHERE created_at < '2023-01-01'
ORDER BY id
LIMIT 1000;          # 循环执行直到影响行数为 0

-- PostgreSQL:用子查询删除关联表数据
DELETE FROM order_items
WHERE order_id IN (
    SELECT id FROM orders WHERE status = 'cancelled'
);

-- 清空整表(不可回滚,谨慎使用)
TRUNCATE TABLE tmp_import;

删除方式对照

方式能否回滚空间回收适用场景
DELETE 带条件可以不立即归还磁盘按条件清理,可分批
DELETE 全表可以不立即归还磁盘小表,或需要触发触发器
TRUNCATE不可以立即释放数据页整表清空且无外键引用
DROP 后重建不可以释放最彻底归档完成后重建表
软删除标记不涉及不涉及生产环境常规做法
DELETE 不带 WHERE 会清空全表:执行前先跑同条件的 SELECT COUNT(*),并在事务内执行确认,这是最低成本的事故拦截。
被删除的行空间不会立刻归还操作系统(InnoDB 常态),表空间回收要靠后续重建表或碎片整理,长期高频删除的表要定期维护。
分批删除的判断条件是「影响行数小于批大小」:当一批删不满时就说明已经删完,可以停止循环,避免空转。
PostgreSQL 的 DELETE 会留下死元组,需要 VACUUM 回收;大批量删除后建议检查 autovacuum 是否及时跟上,否则表和索引会持续膨胀。

分批删除要点

  • 每批较小:一批几百到几千行,避免长事务与锁堆积
  • 按主键或时间序推进:WHERE id > 上次位置,条件稳定且能走索引
  • 批间留间隔:给主从复制与后台任务留出追赶时间
  • 删除前先归档:把数据复制到归档表或冷存储再删
  • 监控主从延迟:延迟超过阈值就暂停,避免影响读库
  • 校验结果:删完对比剩余行数与业务预期是否一致
删除大表数据前先确认有可用的备份或归档:DELETE 可回滚的前提是事务尚未提交,一旦提交,恢复只能依赖备份或日志。
分批删除要和主从延迟监控一起上线:只分批不看延迟,遇到业务高峰期依然可能把从库压垮,暂停与恢复的条件要提前定好。

易错点

  • MySQL 单表 DELETE 支持 ORDER BY 与 LIMIT,多表语法不支持 LIMIT,混写会直接报错
  • 被删除的行空间不会立刻归还操作系统(InnoDB 常态),表空间回收要靠后续重建或碎片整理
  • 一次性删除千万行造成长事务,undo 与 binlog 膨胀,主从延迟飙升
  • 不带 WHERE 的 DELETE 清空全表且可回滚范围有限,属于典型事故场景
  • 删除后忘记清理依赖数据(明细、索引缓存、对象存储文件),留下孤儿数据

数据来源与参考

  • MySQL 8.0 Reference Manual · DELETE
  • PostgreSQL Documentation · DELETE
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌