📄 一句话概括
事务让一组操作要么全成、要么全不做——转账这类【半截不能停】的操作,安全绳交给 DBMS。
📝 本节和前面几节的关系
数据能增删改查了,最后一个问题:如果一组操作做到一半出错了怎么办?本节讲事务。
一、半截操作的灾难
转账要动两条记录:A 扣 100、B 加 100——如果只做完 A 就断电或报错,钱就凭空少了 100; 这类操作的特点是:必须成组完成,不允许停在中间; 自己写代码去补救(手动改回)只是权宜——要考虑的意外太多,顾不过来。
二、事务:把一组操作捆成一件事
BEGIN:开始事务,之后的修改进入临时状态; COMMIT:确认提交,修改正式落盘; ROLLBACK:撤销回滚,把这一组修改全部作废——像什么都没发生过。 三条命令把一组操作捆成【一件事】——这就是事务的原子性:要么全成,要么全不做。
三、为什么交给 DBMS
这件事非 DBMS 不可:它掌握着数据文件与日志(log),就算中途断电,重启后也能照日志把没提交的修改收拾干净; 应用层自己做不了这个保证——它连断电那一刻的数据都摸不到; 【⚠️ 2026 现状】分布式系统把事务扩大到多台机器(分布式事务、最终一致),思路仍是【别停在中间】。
四、动手 Demo:转账与回滚
真跑一次成功转账(COMMIT)与失败转账(ROLLBACK),看余额怎么变。
import sqlite3
con = sqlite3.connect(":memory:", isolation_level=None)
con.execute("CREATE TABLE account (name TEXT PRIMARY KEY, balance INTEGER)")
con.executemany("INSERT INTO account VALUES (?, ?)", [("A", 500), ("B", 200)])
con.execute("BEGIN") # 转账: A-100, B+100
con.execute("UPDATE account SET balance = balance - 100 WHERE name='A'")
con.execute("UPDATE account SET balance = balance + 100 WHERE name='B'")
con.commit() # 提交
print(list(con.execute("SELECT * FROM account")))
con.execute("BEGIN") # 再来一次, 但中途出错
con.execute("UPDATE account SET balance = balance - 100 WHERE name='A'")
con.rollback() # 回滚, 撤销半截操作
print(list(con.execute("SELECT * FROM account")))
实跑输出:
--------------------------------------------------------------------
事务控制也可以交给 DBMS 处理
--------------------------------------------------------------------
转账要动两条记录: A 减 100、B 加 100。若只做完一半就断电, 账目就乱了。
事务让这两步【要么全成, 要么全不做】:
初始:
余额 -> A=500 B=200
[成功案例] BEGIN; A-100; B+100; COMMIT;
提交后 -> A=400 B=300
合计仍是 700: 100 元一分不多一分不少。
[失败案例] BEGIN; A-100; 中途出错; ROLLBACK;
A 已扣、B 未加 -> A=300 B=300
回滚后 -> A=400 B=300
回滚把半截操作全撤销, 账目回到干净状态。
原子性(要么全成)是事务的核心——DBMS 用日志保证断电后也能收拾干净。
第一次提交后合计仍是 700,第二次回滚后余额回到原值——一分不多一分不少,这是事务要守住的底线。 回滚能撤销【半截操作】,靠的是 DBMS 记的日志——所以这项保证必须由 DBMS 来做。
30 秒实验
- 举一个【必须成组完成】的业务动作(转正、下单扣库存),说说半截完成会出什么乱子。
- 说出 BEGIN、COMMIT、ROLLBACK 三个命令各自的作用。
常见误区
- 以为应用层自己补一补就能替代事务——断电、并发时应用什么也保证不了。
- 以为事务只是编程技巧——它是 DBMS 用日志实现的硬保证,是数据库的基本功。
自测三问(点开对答案)
1. 事务的核心性质是什么? —— 原子性——一组操作要么全成、要么全不做。 2. 三个事务命令各做什么? —— BEGIN 开始、COMMIT 提交、ROLLBACK 回滚撤销。 3. 为什么事务必须由 DBMS 负责? —— 它掌数据文件与日志,断电后还能照日志收拾干净。- ☐ 下一节(COLUMN 培训新人编程时推荐使用什么编程语言?)
相关笔记
- LX_CH4_46 — 中断的保存现场与恢复,和回滚是同一种【出事要能收拾】的思想
- 🗄️ 数据库基础 · 索引 — ACID 四性质在那边成体系
- 💻 计算机是怎样跑起来的 · 索引