一、三种核心删除语法:DELETE / TRUNCATE / DROP
1. DELETE 语句(DML 数据操作语言,线上最常用)
1)基础用法
sql
-- 删除符合条件的单/多条数据
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;
关键特性
- 只删表内数据,保留表结构、索引、约束;
- 支持
WHERE条件精准删除,可回滚(事务中执行可ROLLBACK); - 自增主键不重置,下一条新增 id 延续之前最大值;
- 逐条删除,写入 undo 日志,数据量大时性能极差;
- 会触发触发器、逻辑删除拦截、事务锁;
- 支持 LIMIT 限制删除行数,避免一次性删百万数据锁表:
sql
-- 每次删1000条,分批删除大表数据
DELETE FROM log_info WHERE id < 100000 LIMIT 1000;
适用场景
- 精准删除单条 / 少量业务数据;
- 线上删除指定订单、商品、用户;
- 需要支持事务回滚的删除操作;
- 保留自增 id 连续性的业务。
2. TRUNCATE TABLE
sql
TRUNCATE TABLE product_category;
-- 简写
TRUNCATE product_category;
关键特性
- 清空表所有数据,不支持 WHERE 条件,无法删部分数据;
- 保留表结构、字段、索引,重置自增主键为 1;
- 底层直接销毁重建数据页,不记录 undo 日志,速度极快(百万级数据秒清);
- 不可回滚,事务中执行也无法撤销;
- 会清空统计信息,外键关联表禁止直接 truncate;
- 不触发删除触发器。
适用场景
- 测试环境清空测试表数据;
- 定期清理独立日志表(无外键、无业务关联);
- 全新初始化表,需要重置自增 ID。
生产红线
线上业务主表禁止随便执行 TRUNCATE,一旦执行整表数据清空且无法回滚。
3. DROP TABLE
sql
DROP TABLE IF EXISTS product_category;
关键特性
- 直接删除整张表:数据 + 表结构 + 索引 + 约束全部销毁;
- 释放磁盘空间,无法恢复(无备份直接丢表);
- IF EXISTS 避免表不存在时报错。
适用场景
废弃不用的旧表、历史临时表,确认永久不再使用才执行。
二、业务层「逻辑删除」
原理
不执行任何 DELETE 物理删除 SQL,通过标记字段区分数据是否有效
- 表增加字段:
is_delete TINYINT DEFAULT 0 COMMENT 0正常 1已删除 - 删除操作改为 UPDATE 更新标记:
sql
UPDATE product_category SET is_delete = 1 WHERE id = 10;
- 查询时强制过滤已删除数据:
sql
SELECT * FROM product_category WHERE is_delete = 0;
MyBatis-Plus 自动逻辑删除配置(你项目在用)
- yml 全局配置
yaml
mybatis-plus:
global-config:
db-config:
logic-delete-field: isDelete
logic-delete-value: 1
logic-not-delete-value: 0
- 实体加注解
java
运行
@TableLogic
private Integer isDelete;
- 调用
mapper.deleteById(10L),MP 自动执行 UPDATE,不会执行 DELETE。
优势
- 数据可恢复,防止误删订单、商品等核心业务数据;
- 支持数据溯源、对账、售后纠纷查询;
- 避免物理删除带来的锁表、事务风险。
适用场景
电商订单、商品、用户、支付流水、交易类核心业务表(强制逻辑删除)。
三、批量删除优化方案
方案 1:DELETE 分批删除
避免一次性删除几十万行锁表阻塞业务:
sql
-- 循环执行,每次删1000条,直到无数据
DELETE FROM operation_log WHERE create_time < '2026-01-01' LIMIT 1000;
方案 2:分表归档 + TRUNCATE
历史日志按月分表,直接 truncate 过期月份分表,不影响主业务表。
方案 3:新建空表替换
- 复制原表结构
CREATE TABLE log_new LIKE log_old; - 交换表名
RENAME TABLE log_old TO log_bak, log_new TO log_old; - 备份完成后 DROP 备份表。
四、四种删除方式核心对比表
表格
| 方式 | 语法类型 | 是否删表结构 | 支持条件 WHERE | 自增 ID | 可回滚 | 速度 | 生产业务表推荐 |
|---|---|---|---|---|---|---|---|
| DELETE | DML | 保留 | ✅支持 | 不重置 | ✅事务可回滚 | 慢(量大阻塞) | 少量精准删除 |
| TRUNCATE | DDL | 保留 | ❌不支持 | 重置为 1 | ❌不可回滚 | 极快 | 测试 / 独立日志表 |
| DROP TABLE | DDL | 全部删除 | ❌不支持 | 无 | ❌不可回滚 | 快 | 废弃无用表 |
| 逻辑删除 UPDATE | DML | 完全保留 | ✅支持 | 不变 | ✅可恢复 | 快 | 电商核心业务(首选) |
五、生产环境删除数据规范 & 避坑
- 核心业务表禁止物理删除(订单、支付、商品、用户),统一逻辑删除;
- 执行 DELETE 大批量数据前,先 SELECT 核对删除行数,避免误删;
- 线上禁止无 WHERE 的
DELETE FROM 表名,会锁全表; - TRUNCATE 严禁在主业务表执行,执行前必须全量备份;
- 删除操作尽量避开业务高峰(凌晨低流量执行);
- 外键关联表删除时,先删子表数据,再删主表,防止外键报错;
- 误删急救:提前开启 binlog 二进制日志,可通过 binlog 恢复误删数据。
六、补充:关联表级联删除
建表时设置外键 ON DELETE CASCADE,删除主表数据自动同步删除子表关联数据
sql
CREATE TABLE order_item(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id BIGINT,
FOREIGN KEY (order_id) REFERENCES order_info(id) ON DELETE CASCADE
);
删除订单主表数据,订单明细会自动删除;电商项目不推荐使用,级联删除不可控,容易误删大量数据,业务代码手动控制删除明细更安全。