一:事务隔离级别
(1)MySQL的四种事务隔离级别
MySQL数据库支持四种事务隔离级别,这些级别定义了一个事务可能读取另一个并发事务所写的数据的方式。这些级别旨在平衡性能和一致性,不同的级别会在防止事务中的不同问题(如脏读、不可重复读和幻读)之间取得不同的平衡。这四个级别分别是
- 读未提交(Read Uncommitted):
- 这是最低的隔离级别。
- 在这个级别,事务可以读取其他未提交事务的修改。
- 这意味着它可能会读到脏数据(dirty data),即那些可能最终不会被提交的数据。
- 该级别提供的隔离性最差,但性能开销最小。
- 读已提交(Read Committed):
- 事务只能读取到已经提交的数据。
- 这避免了脏读,但不可重复读(non-repeatable reads)仍然可能发生。不可重复读是指在同一个事务中,两次读取同一数据集合可能会得到不同的结果。
- 这个级别在许多数据库系统中是默认设置。
- 可重复读(Repeatable Read):
- 这是MySQL默认的事务隔离级别。
- 在这个级别,保证了在同一个事务中多次读取同一数据会得到相同的结果,避免了不可重复读。
- 然而,幻读(phantom reads)仍然可能发生。幻读是指当一个事务在两次查询之间,另一个事务插入了新的行,导致第二次查询返回了额外的行。
- 串行化(Serializable):
- 这是最高的隔离级别。
- 事务被完全串行执行,避免了脏读、不可重复读和幻读
- 这通过锁定涉及到的数据行来实现,因此可能会导致大量的锁等待和降低并发性能
隔离级别 | 脏读(Dirty Read) | 不可重复读(Non-repeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
读未提交(Read Uncommitted) | 可能 | 可能 | 可能 |
读已提交(Read Committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatable Read) | 不可能 | 不可能 | 可能 |
串行化(Serializable) | 不可能 | 不可能 | 不可能 |
(2)Spring事务隔离级别
在Spring中,事务隔离级别通常在服务层通过@Transactional
来配置。包括:
@Transactional(isolation=Isolation.DEFAULT)
:以连接的数据库的事务隔离级别为主@Transactional(isolation=Isolation.READ_UNCOMMITTED)
:读未提交- 这个级别允许一个事务读取另一个事务未提交的更改
- 它可能导致脏读、不可重复读和幻读
@Transactional(isolation=Isolation.COMMITTED)
:读已提交- 这个级别确保一个事务只能读取已经提交的数据
- 它防止脏读,但不可重复读和幻读仍然可能发生
@Transactional(isolation=Isolation.REPEATABLE_READ)
:可重复读- 在这个级别,保证在同一个事务中多次读取同一数据会得到相同的结果
- 它防止了脏读和不可重复读,但幻读可能仍然发生
@Transactional(isolation=Isolation.SERIALIZABLE)
:串行化- 这是最高的隔离级别,确保所有事务依次序列化执行,从而防止了脏读、不可重复读和幻读
- 但这种级别可能会引起性能问题,因为它可以导致大量的锁等待
二:事务传播机制
Spring框架提供了丰富的事务管理功能,其中事务传播行为是一个核心概念。事务传播行为定义了业务方法相对于事务的执行方式。当在业务方法中调用另一个业务方法时,事务传播行为决定了是否要在现有事务中运行该方法,还是要为其创建一个新的事务。
- REQUIRED(默认):如果当前存在事务,那么方法将会在这个事务内运行;否则,它将启动一个新的事务。
- SUPPORTS:如果当前存在事务,方法将在这个事务内运行;如果没有事务,它也可以以非事务的方式执行。
- MANDATORY:如果当前存在事务,方法将在这个事务内运行;如果没有活动事务,将抛出异常。
- REQUIRES_NEW:总是开启一个新的事务。如果当前存在事务,将当前事务挂起。
- NOT_SUPPORTED:方法总是非事务性执行,如果当前存在事务,则将当前事务挂起。
- NEVER:方法总是非事务性执行,如果当前存在事务,则抛出异常。
- NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则其行为与REQUIRED一样
评论区