全书目录

第十八篇:MySQL 完全指南 —— 城市户籍总账宇宙

第九章:事务 —— 一次迁户办理,要么全成,要么全不算

1 分钟 322 字 第 344 / 962 个阅读单元

事务解决的是“半成品状态”。

例如,迁户口是一件完整办理:

  1. 锁定当前市民记录
  2. 修改其所属户号
  3. 写迁移日志
  4. 全部成功才算办理完成

这就应该放进一个事务里。

sql
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;

如果中途有一步失败:

sql
ROLLBACK;

事务的核心就是:

这批操作要么一起盖章入账,要么整批作废。

这里还有一个非常重要的 MySQL 现实:

MySQL 默认是 autocommit = 1

也就是如果你不显式开启事务,那么很多 SQL 都是“执行完就自动提交”。所以你不能以为自己写了两条 UPDATE,它们就天然算同一个事务。

再提醒一个常见坑:

不是所有语句都能像普通 DML 一样回滚。 特别是很多 DDL 语句会触发隐式提交,所以“边改表边指望事务回滚”是很危险的想法。