MySQL删除数据全方式详解

 更新时间:2026年07月13日 08:57:17   作者:从此以后自律  
还在纠结用DELETE、TRUNCATE还是DROP,本文深度对比MySQL四种删除方式,从语法、性能到生产避坑一网打尽,告诉你为什么电商核心业务必须用逻辑删除,以及如何通过分批删除和归档优化大表清理,助你安全高效管理数据,需要的朋友可以参考下

一、三种核心删除语法:DELETE / TRUNCATE / DROP

1. DELETE 语句(DML 数据操作语言,线上最常用)

1)基础用法

-- 删除符合条件的单/多条数据
DELETE FROM product_category WHERE id = 10;
-- 删除整张表全部数据(不推荐,量大性能差)
DELETE FROM product_category;
-- 多条件删除
DELETE FROM order_info WHERE create_time < '2026-01-01' AND is_delete = 0;

关键特性

  1. 只删表内数据,保留表结构、索引、约束
  2. 支持 WHERE 条件精准删除,可回滚(事务中执行可 ROLLBACK);
  3. 自增主键不重置,下一条新增 id 延续之前最大值;
  4. 逐条删除,写入 undo 日志,数据量大时性能极差;
  5. 会触发触发器、逻辑删除拦截、事务锁;
  6. 支持 LIMIT 限制删除行数,避免一次性删百万数据锁表:
-- 每次删1000条,分批删除大表数据
DELETE FROM log_info WHERE id < 100000 LIMIT 1000;

适用场景

  • 精准删除单条 / 少量业务数据;
  • 线上删除指定订单、商品、用户;
  • 需要支持事务回滚的删除操作;
  • 保留自增 id 连续性的业务。

2. TRUNCATE TABLE

TRUNCATE TABLE product_category;
-- 简写
TRUNCATE product_category;

关键特性

  1. 清空表所有数据,不支持 WHERE 条件,无法删部分数据;
  2. 保留表结构、字段、索引,重置自增主键为 1
  3. 底层直接销毁重建数据页,不记录 undo 日志,速度极快(百万级数据秒清);
  4. 不可回滚,事务中执行也无法撤销;
  5. 会清空统计信息,外键关联表禁止直接 truncate;
  6. 不触发删除触发器。

适用场景

  • 测试环境清空测试表数据;
  • 定期清理独立日志表(无外键、无业务关联);
  • 全新初始化表,需要重置自增 ID。

生产红线

线上业务主表禁止随便执行 TRUNCATE,一旦执行整表数据清空且无法回滚。

3. DROP TABLE

DROP TABLE IF EXISTS product_category; 

关键特性

  1. 直接删除整张表:数据 + 表结构 + 索引 + 约束全部销毁
  2. 释放磁盘空间,无法恢复(无备份直接丢表);
  3. IF EXISTS 避免表不存在时报错。

适用场景

废弃不用的旧表、历史临时表,确认永久不再使用才执行。

二、业务层「逻辑删除」

原理

不执行任何 DELETE 物理删除 SQL,通过标记字段区分数据是否有效

  1. 表增加字段:is_delete TINYINT DEFAULT 0 COMMENT 0正常 1已删除
  2. 删除操作改为 UPDATE 更新标记:
UPDATE product_category SET is_delete = 1 WHERE id = 10; 
  1. 查询时强制过滤已删除数据:
SELECT * FROM product_category WHERE is_delete = 0; 

MyBatis-Plus 自动逻辑删除配置(你项目在用)

  1. yml 全局配置
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: isDelete
      logic-delete-value: 1
      logic-not-delete-value: 0
  1. 实体加注解
@TableLogic
private Integer isDelete;
  1. 调用 mapper.deleteById(10L),MP 自动执行 UPDATE,不会执行 DELETE。

优势

  • 数据可恢复,防止误删订单、商品等核心业务数据;
  • 支持数据溯源、对账、售后纠纷查询;
  • 避免物理删除带来的锁表、事务风险。

适用场景

电商订单、商品、用户、支付流水、交易类核心业务表(强制逻辑删除)。

三、批量删除优化方案

方案 1:DELETE 分批删除

避免一次性删除几十万行锁表阻塞业务:

-- 循环执行,每次删1000条,直到无数据
DELETE FROM operation_log WHERE create_time < '2026-01-01' LIMIT 1000;

方案 2:分表归档 + TRUNCATE

历史日志按月分表,直接 truncate 过期月份分表,不影响主业务表。

方案 3:新建空表替换

  1. 复制原表结构 CREATE TABLE log_new LIKE log_old;
  2. 交换表名 RENAME TABLE log_old TO log_bak, log_new TO log_old;
  3. 备份完成后 DROP 备份表。

四、四种删除方式核心对比表

表格

方式语法类型是否删表结构支持条件 WHERE自增 ID可回滚速度生产业务表推荐
DELETEDML保留✅支持不重置✅事务可回滚慢(量大阻塞)少量精准删除
TRUNCATEDDL保留❌不支持重置为 1❌不可回滚极快测试 / 独立日志表
DROP TABLEDDL全部删除❌不支持❌不可回滚废弃无用表
逻辑删除 UPDATEDML完全保留✅支持不变✅可恢复电商核心业务(首选)

五、生产环境删除数据规范 & 避坑

  1. 核心业务表禁止物理删除(订单、支付、商品、用户),统一逻辑删除;
  2. 执行 DELETE 大批量数据前,先 SELECT 核对删除行数,避免误删;
  3. 线上禁止无 WHERE 的 DELETE FROM 表名,会锁全表;
  4. TRUNCATE 严禁在主业务表执行,执行前必须全量备份;
  5. 删除操作尽量避开业务高峰(凌晨低流量执行);
  6. 外键关联表删除时,先删子表数据,再删主表,防止外键报错;
  7. 误删急救:提前开启 binlog 二进制日志,可通过 binlog 恢复误删数据。

六、补充:关联表级联删除

建表时设置外键 ON DELETE CASCADE,删除主表数据自动同步删除子表关联数据

CREATE TABLE order_item(
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id BIGINT,
    FOREIGN KEY (order_id) REFERENCES order_info(id) ON DELETE CASCADE
);

删除订单主表数据,订单明细会自动删除;电商项目不推荐使用,级联删除不可控,容易误删大量数据,业务代码手动控制删除明细更安全。

以上就是MySQL删除数据全方式详解的详细内容,更多关于MySQL删除数据方式的资料请关注脚本之家其它相关文章!

相关文章

最新评论