事务解决的是“半成品状态”。
例如,迁户口是一件完整办理:
- 锁定当前市民记录
- 修改其所属户号
- 写迁移日志
- 全部成功才算办理完成
这就应该放进一个事务里。
START TRANSACTION;
SELECT household_id
FROM citizens
WHERE citizen_id = 1
FOR UPDATE;
UPDATE citizens
SET household_id = 2,
status = 'active'
WHERE citizen_id = 1;
INSERT INTO move_logs (
citizen_id,
from_household_id,
to_household_id,
reason
) VALUES (
1,
1,
2,
'工作调动'
);
COMMIT;如果中途有一步失败:
ROLLBACK;事务的核心就是:
这批操作要么一起盖章入账,要么整批作废。
这里还有一个非常重要的 MySQL 现实:
MySQL 默认是 autocommit = 1。
也就是如果你不显式开启事务,那么很多 SQL 都是“执行完就自动提交”。所以你不能以为自己写了两条 UPDATE,它们就天然算同一个事务。
再提醒一个常见坑:
不是所有语句都能像普通 DML 一样回滚。 特别是很多 DDL 语句会触发隐式提交,所以“边改表边指望事务回滚”是很危险的想法。