测试环境的表造了几十万条脏数据,想一把清空重来,用了 DELETE FROM 跑半天还没完。mysql 清空表有两个写法,速度和副作用差别很大,选错一个能卡一晚上。
TRUNCATE:一把清空
TRUNCATE TABLE order_log;直接把表数据全删,速度极快,自增 ID 归零,重新插数据从 1 开始。它属于 DDL 操作,多数情况不能回滚,也不能加 WHERE 条件,就是全清。权限要求也高,账号得有 DROP 权限,普通只有增删改查权限的账号跑不了这条。
DELETE:可条件可回滚
DELETE FROM order_log WHERE created_at < '2025-01-01'; DELETE FROM order_log;DELETE 一行一行删,能带条件、能放进事务里回滚,但全表清空时比 TRUNCATE 慢得多,而且自增 ID 不会重置,再插入会接着旧的最大值往上走。顺便说一句,DELETE 之后表文件大小一般不会立刻变小,InnoDB 的空间不会马上还给系统,介意的话得用重建表的方式回收。
还有一个 DROP
DROP TABLE 连表带结构一起删,重建得重新 CREATE。需求是「表还要用,只清数据」,就轮不到它。误删整张表想恢复,只能靠备份或延迟从库,难度比清空数据高一个量级。
实际怎么选
- 开发测试环境清库重来:TRUNCATE,快,ID 从头计
- 生产环境删部分数据:DELETE 加 WHERE,先 SELECT 确认影响行数再删
- 大表全清又要求可回滚:分批 DELETE,避免长事务锁表
- 只清到某个时间点:DELETE 加范围条件,分批提交
动手前留一手
备份命令一行:mysqldump -u用户名 -p 库名 表名 > backup.sql,恢复时用 source 导回去。测试库随便清,生产库先备份再动手,这个习惯关键时刻能救急。
生产库上执行 TRUNCATE 前多想十秒:它不能回滚,条件都没得加,删错了只能从备份捞。mysql 清空表之前顺手备份一份,mysqldump 一条命令的事。