只有在事务未提交时,ROLLBACK才能撤销DELETE;已提交的DELETE无法回滚。因MySQL/SQL Server默认autocommit=1,单条DELETE自动提交,ROLLBACK无目标;须先START TRANSACTION,再DELETE,最后ROLLBACK或COMMIT。

只有在事务未提交时,ROLLBACK 才能真正撤销 DELETE;已提交的删除无法靠事务机制回退。
为什么刚删完就 ROLLBACK 却没用?
最常见的情况是:你执行了 DELETE FROM users WHERE id = 123;,立刻敲 ROLLBACK;,但数据没回来。这不是命令写错了,而是数据库根本没把它放进可回滚的上下文中。
- MySQL 默认
autocommit = 1,每条DELETE都是独立事务,执行完自动COMMIT,ROLLBACK找不到目标 - SQL Server 同样默认自动提交,单独一条
DELETE不在事务块内,ROLLBACK TRANSACTION会报错 “no transaction or savepoint with that name” - PostgreSQL 默认关闭
autocommit,但如果你没显式BEGIN或START TRANSACTION,而是在 psql 中直接执行DELETE,它仍会自动提交(psql 的 \set autocommit on 是默认行为)
让 ROLLBACK 真正生效的三步闭环
关键不是“怎么回滚”,而是“怎么让删除处于可回滚状态”。这需要提前控制事务生命周期:
- 先显式开启事务:
START TRANSACTION;(MySQL)、BEGIN TRANSACTION;(SQL Server)、BEGIN;(PostgreSQL) - 再执行
DELETE—— 此时变更只在内存和 undo log 中暂存,未写入数据文件 - 删完立刻验证:
SELECT * FROM table WHERE ...,确认删对了再COMMIT;,否则直接ROLLBACK;
示例(MySQL):
START TRANSACTION; DELETE FROM orders WHERE order_id = 998877; SELECT COUNT(*) FROM orders WHERE order_id = 998877; -- 应为 0 ROLLBACK; -- 数据立即恢复
哪些场景下 ROLLBACK 一定无效?
一旦 DELETE 已落地,事务机制就彻底退出舞台。以下情况 ROLLBACK 不起作用:
-
DELETE执行时autocommit = 1(MySQL/SQL Server 默认),且未手动BEGIN - 客户端(如 MySQL Workbench、SSMS)设置了自动提交,你没察觉
- ORM 框架(如 Django ORM、MyBatis)执行
delete()时默认提交,未包裹在事务装饰器或transaction.atomic中 - 误用了
TRUNCATE TABLE或DROP TABLE—— 它们是 DDL,不支持事务回滚(MySQL 中TRUNCATE在事务中也不可回滚)
执行 ROLLBACK 前最容易被忽略的检查点
很多人卡在“明明开了事务却回滚失败”,问题往往出在连接和会话层面:
- 确认当前会话没被意外断开或重连 ——
ROLLBACK必须在同一个数据库连接中执行 - 检查是否嵌套了多个事务:SQL Server 不支持真嵌套事务,外层
COMMIT后内层ROLLBACK会报错 - PostgreSQL 中若用了
SAVEPOINT,必须ROLLBACK TO SAVEPOINT sp_name,而不是裸ROLLBACK - 某些中间件(如 ProxySQL、ShardingSphere)可能拦截或改写事务控制语句,导致实际未进入事务
事务安全的本质不是“删完能撤”,而是“删之前已设好逃生舱门”。一旦删完才发现没开舱门,就只能转向日志或备份恢复——那已是另一套操作体系了。

















