❤ 面试题
请简单介绍 Spring 支持的常用数据库事务传播属性和事务隔离级别?
❤ 事务的属性
1、propagation:用来设置事务的传播行为
2、isolation:用来设置事务的隔离级别
❤ propagation 事务的传播行为
1、什么是事务的传播行为?
- 一个方法运行在了一个开启了事务的方法中时,当前方式是使用原来的事务还是开启一个新的事务。
2、 事务的传播属性值:有 7 种,详见表格。
- Propagation.REQUIRED:默认值,使用原来的事务。
Propagation.REQUIRES_NEW:将原来的事务挂起,开启一个新的事务。
疑问待处理:事务的传播 required 与 nested 区别?(视频中未说明)

❤ isolation 事务的隔离级别
- Isolation.REPEATABLE_READ:可重复读,MySQL 默认的隔离级别。
- Isolation.READ_COMMITED:读已提交,Oracle 默认的隔离级别,开发时通常使用的隔离级别。
1、 数据库事务的并发问题
(1) 脏读:读取了别人更新但是没有提交的数据
(2) 不可重复读:两次读取的数据内容不一致。
(3) 幻读:两次读取的行数不一致

2、隔离级别
- 注意:隔离级别并非越高越好!过高会导致性能下降!
(1) 隔离级别

(2) 隔离级别的并发能力

(3) 数据库产品对事务隔离级别的支持程度

一、场景描述
1、数据库表
(1) account:账户

(2) book:图书
- 说明:isbn:国际标准序号

(3) book_stock:库存

2、代码实现
(1) 接口 BookShopService

(2) 接口 Cashier

(3) 实现类 BookShopServiceImpl

(4) 实现类 CashierImpl

(5) 测试类 TxTest

二、事务的传播行为
1、问题引入
100 < 60+ 50,用户的余额100 不足以同时购买 1001 和 1002 两本书。那么最后结果是能够买成功一本?还是全部失败呢?此时就需要关注事务的传播行为。
对应到代码中,当前 checkout 和 purchase 方法都设置了事务。如果在 checkout 方法中调用了 purchase 方法,purchase 方法使用的是哪个方法的事务?(所在方法 checkout 的事务?还是自身的事务?)此时就需要关注到事务的传播属性,不同的属性值对所产生的结果各不相同!
2、REQUIRED(默认)
(1) TxTest 执行结果:全部失败!数据库无变化。

(2) 结果原因分析

3、REQUIRES_NEW
(1) TxTest 执行结果:成功购买一本。数据库变化如下:
- 数据库余额 account.balance 变成 40,
- book_stock 变成 99


(2) 结果原因分析

三、事务的隔离级别
1、演示:可重复读 REPEATABLE_READ(MySQL 默认)
(1) purchase 方法
- 设置隔离级别:可重复读 REPEATABLE_READ
- 两次读取

(2) 单元测试 TxTest
- 第1次读取后,暂停:价格为60
- 手动将60修改为600
- 第2次读取:价格依然为60,两次读取数据一致!



2、演示:读已提交 READ_COMMITTED
- 过程同上,略
- 结果:第2次读取价格变为600,为中途修改后的数据!


☀ 课堂小测
- 回答面试题。
- 什么是事务?
- 事务的应用场景?
- 事务的属性有哪些?
- 什么是事务的传播行为?传播属性有哪些?各自的应用?
- 什么是事务的隔离级别?隔离级别有哪些?各自的应用?
- 隔离级别的并发能力?
- 数据库产品对事务隔离级别的支持程度?
- mysql 默认?orcale默认?
- mysql 默认?orcale默认?
- 隔离级别的并发能力?
- 分别介绍脏读、错读、幻读?
- 疑问待处理:事务的传播 required 与 nested 区别?(视频中未说明)
