数据库原理与应用 第 9 章 · 第三节
课程 › 第 9 章 › 第三节 四种级别读未提交读已提交可重复读串行化 版式
第 9 章 数据库并发控制与封锁 · 第三节

事务的隔离级别

SQL 标准的四种隔离级别,查看和设置隔离级别,以及例 9-2 到例 9-4
本 节 知 识 点
  1. 10四种隔离级别
  2. 11读未提交(例 9-2)
  3. 12读已提交(例 9-3)
  4. 13可重复读(例 9-4)
  5. 14串行化与四种级别的对照
10
第 9 章 · 第三节 · 课件第 19、20 页合并重做

四种隔离级别

级别越高,出现的问题越少,并发程度越低。

9.4 事务的隔离级别课件第 19、20 页合并

四种隔离级别

四种数据不一致性都是因为并发的事务破坏了隔离性。SQL 标准定义了四种隔离级别,级别越高,出现的问题越少,并发程度越低。
级别写法说明
读未提交READ UNCOMMITTED最低,可以读到其他事务未提交的数据
读已提交READ COMMITTED只能读到其他事务已提交的数据
可重复读REPEATABLE READMySQL 的默认级别
串行化SERIALIZABLE最高,事务一个接一个执行
查看当前会话的隔离级别
SELECT @@transaction_isolation;
设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL
    READ COMMITTED;
  • SESSION:只对当前会话有效,实验中都用这种写法
  • GLOBAL:对以后新建立的会话有效
  • 也可以写成 SET transaction_isolation = 'READ-COMMITTED',级别名中的空格改为短横线
11
第 9 章 · 第三节 · 课件第 21、22、23 页合并重做

读未提交(例 9-2)

可以读到其他事务未提交的数据。

9.4 事务的隔离级别课件第 21、22、23 页合并

读未提交(例 9-2)

T1 设为读未提交。T2 给 account1 存入 100 元,还没有提交时,T1 读取余额。
① T1
SET SESSION TRANSACTION ISOLATION LEVEL
    READ UNCOMMITTED;
START TRANSACTION;
SELECT * FROM account;
② T2
START TRANSACTION;
UPDATE account SET R = R + 100
WHERE id = 'account1';
③ T1
SELECT * FROM account;
T1 两次查到的 account1
查询account1 的余额
第一次,步骤 ①500
第二次,步骤 ③600
  • 第二次读到了 T2 还没有提交的数据,发生了读脏数据。T2 一旦回滚,600 就不存在了
  • 读未提交不能避免读脏数据、不可重复读和幻象读

重 点

两个事务要在 Workbench 的两个连接窗口中交替执行,一个窗口做不出并发的效果。

实 验

实验 2-2 读未提交:读到脏数据

12
第 9 章 · 第三节 · 课件第 24、25、26、27 页合并重做

读已提交(例 9-3)

只读已提交的数据,避免了读脏数据。

9.4 事务的隔离级别课件第 24、25、26、27 页合并

读已提交(例 9-3)

T1 设为读已提交。T2 存入 100 元但不提交,T1 再读,T2 提交后,T1 第三次读。
① T1
SET SESSION TRANSACTION ISOLATION LEVEL
    READ COMMITTED;
START TRANSACTION;
SELECT * FROM account;
② T2
START TRANSACTION;
UPDATE account SET R = R + 100
WHERE id = 'account1';
③ T1
SELECT * FROM account;
④ T2
COMMIT;
⑤ T1
SELECT * FROM account;
T1 三次查到的 account1
查询account1 的余额
第一次,步骤 ①500
第二次,步骤 ③500
第三次,步骤 ⑤600
  • 第二次读不到 T2 未提交的数据,避免了读脏数据
  • 第三次读到了 T2 提交的数据,与前两次不同,出现了不可重复读
  • 读已提交不能避免不可重复读和幻象读
13
第 9 章 · 第三节 · 课件第 28、29、30 页合并重做

可重复读(例 9-4)

同一事务中多次读取,结果相同。

9.4 事务的隔离级别课件第 28、29、30 页合并

可重复读(例 9-4)

可重复读是 MySQL 的默认级别。同一个事务中执行相同的查询,读到的结果相同。
① T1
SET SESSION TRANSACTION ISOLATION LEVEL
    REPEATABLE READ;
START TRANSACTION;
SELECT * FROM account;
② T2
START TRANSACTION;
UPDATE account SET R = R + 100
WHERE id = 'account1';
SELECT * FROM account;
COMMIT;
③ T1
SELECT * FROM account;
查到的 account1
查询余额
T1 第一次,步骤 ①500
T2 自己查,步骤 ②600
T1 第二次,步骤 ③500
  • T2 提交后,T1 在同一事务中读到的仍是 500,避免了不可重复读
  • T1 提交事务后再查询,才会读到 600

SQL 标准规定可重复读级别下仍可能出现幻象读。在 MySQL 中,这个级别下的普通查询读的是同一份数据,其他事务新插入并提交的行也看不到。

14
第 9 章 · 第三节 · 课件第 31、32 页合并重做

串行化与四种级别的对照

串行化最高,事务排队执行。

9.4 事务的隔离级别课件第 31、32 页合并

串行化与四种级别的对照

串行化是最高的隔离级别,强制事务一个接一个执行,可以避免幻象读,但可能导致大量等待。
隔离级别丢失更新读脏数据不可重复读幻象读
读未提交
读已提交√
可重复读√√√
串行化√√√√

√ 表示这一级别能够避免这种问题

  • 乐观并发控制:假定不会发生冲突,允许并发执行,真的冲突时再处理,例如回滚事务
  • 悲观并发控制:假定一定会发生冲突,操作之前先加锁
表中“丢失更新”一列按教材填写。在 MySQL 中,修改数据时总会给行加 X 锁,用 R = R - 100 这样的语句同时修改同一行,在任何隔离级别下都不会丢失更新。

练一练

只要避免读脏数据,允许不可重复读,最低可以选哪个级别?
  1. A读未提交
  2. B读已提交
  3. C可重复读
答案 B

读已提交能避免读脏数据,但不能避免不可重复读。

实 验

实验 2-5 串行化

保山学院·人工智能教研室·曹鼎鼎