🗄️ 第四章 管理数据-避免非法数据的功能
📄 一句话概括

事务把多条 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 前的原样

三、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 后自己这边也回到旧值。

六、常见误区

自测三问 1. 事务解决什么问题?(多条 SQL「做一半」的中间状态) 2. BEGIN/COMMIT/ROLLBACK 各干什么?(宣告整体/交付生效/整体撤销) 3. 下单一动三张表,靠什么保证?(事务捆成一个整体)

相关笔记