📄 一句话概括
事务把多条 SQL 捆成一个整体:要么全部成功,要么全部不算数——不存在「做了一半」的中间状态。银行转账是它的标准画像:扣款和入账必须同生共死。
📝 本节和前面几节的关系
约束(4-6~4-13)管的是单条数据合规;事务管的是一组操作的整体性——另一路防线。第一章 1-8 埋的种子(购物网站下单「一动三张表」)在本节正式回收:那「三张表」就是被事务捆在一起的。
一、没有事务的世界:转账事故
A 给 B 转 100 元,数据库要跑两条 UPDATE:
UPDATE accounts SET balance = balance - 100 WHERE name = 'A'; -- 扣款
UPDATE accounts SET balance = balance + 100 WHERE name = 'B'; -- 入账
第一条成功、第二条断电:A 的钱没了,B 没收到——100 元凭空蒸发。约束拦不住这种事(每条 UPDATE 单独看都合法),缺的是「两条算一件事」的机制。
二、事务三件套
BEGIN; -- 开工:从这里起,所有操作进「草稿区」
UPDATE ... -- 扣款
UPDATE ... -- 入账
COMMIT; -- 交付:草稿一次性转正
-- 或
ROLLBACK; -- 反悔:草稿全部作废,回到 BEGIN 前的原样
BEGIN:宣布「下面这批算一件事」COMMIT:全对,一次性生效(4-15 细讲)ROLLBACK:出事,一次性撤销(4-16 细讲)
三、ACID 四特性(听个耳熟)
| 特性 | 一句话 |
|---|---|
| Atomicity 原子性 | 不可分割:全成或全不算 |
| Consistency 一致性 | 前后都是合法状态(钱守恒) |
| Isolation 隔离性 | 各事务互不偷看(4-17 死锁的温床) |
| Durability 持久性 | COMMIT 后断电也不丢 |
本课重点吃透 A(原子性),其余混个脸熟。
四、动手 Demo:转账的正反两面
PRAGMA foreign_keys = ON;
CREATE TABLE accounts (name VARCHAR(20), balance DECIMAL(10,2));
INSERT INTO accounts VALUES ('甲', 1000), ('乙', 500);
-- 情形一:顺利转 100
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE name = '甲';
UPDATE accounts SET balance = balance + 100 WHERE name = '乙';
COMMIT;
-- 甲 900,乙 600 ✅
-- 情形二:转到一半发现乙的账号冻结,反悔
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE name = '甲';
-- ……业务检查发现问题!
ROLLBACK;
-- 甲还是 900,一分没少 ✅
两条 UPDATE 被 BEGIN/COMMIT(或 ROLLBACK)捆成了一个不可分割的动作。
五、30 秒实验
在 BEGIN 之后 UPDATE 完但还没 COMMIT 时,另开一个查询窗口查同一张表——看到的还是旧值(隔离性在工作)。执行 ROLLBACK 后自己这边也回到旧值。
六、常见误区
- 「每条 SQL 天然安全,不用事务」:单条安全,多条组合(转账、下单、搬库)必须捆事务
- 「事务是为了快」:它为了对;换来的是复杂度(死锁等,4-17)——只在真正「不可分割」的操作上用
自测三问
1. 事务解决什么问题?(多条 SQL「做一半」的中间状态) 2. BEGIN/COMMIT/ROLLBACK 各干什么?(宣告整体/交付生效/整体撤销) 3. 下单一动三张表,靠什么保证?(事务捆成一个整体)- ☐ 下一节(4-15 COMMIT-执行一组处理)
相关笔记
- FOREIGN KEY、外键-与其他表进行关联 —— 上一节:约束防线的终点
- COMMIT-执行一组处理 —— 下一节:草稿转正的那一刻
- 图书馆、购物网站-我们周围使用的数据库 —— 「一动三张表」伏笔在此回收
- 🗄️ 数据库基础 · 索引 —— 全课路线图