spring 的事务隔离有什么作用?
用来解决并发事务所产生一些问题,并发会产生什么问题?
- 1.脏读
- 2.不可重复度
- 3.幻影读
事务隔离的概念
- 通过设置隔离级别可解决在并发过程中产生的那些问题
分别举例说明
1.脏读
上述图表示:一个事务,读取了另一个事务中没有提交的数据,会在本事务中产生的数据不一致的问题
解决方式:
- 使用 注解: @Transactional(isolation = Isolation.READ_COMMITTED)
解释说明:
- 读已提交:READ COMMITTED
- 要求Transaction01只能读取Transaction02已提交的修改。
2.不可重复度
上述图表示:一个事务中,多次读取相同的数据, 但是读取的结果不一样, 会在本事务中产生数据不一致的问题
解决方式:
- 使用注解:@Transactional(isolation = Isolation.REPEATABLE_READ)
解释说明:
- 可重复读:REPEATABLE READ
- 确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更
新。(行锁)
3.幻影读
上述图表示:一个事务中,多次对数据进行整表数据读取(统计),但是结果不一样, 会在本事务中产生数据不一致的问题。
解决方式:
- 使用注解:@Transactional(isolation = Isolation.SERIALIZABLE)
解释说明:
- 串行化:SERIALIZABLE
- 确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更
新、删除操作。可以避免任何并发问题,但性能十分低下。(表锁)
加深理解
很多人容易搞混不可重复读和幻读,确实这两者有些相似:
- 对于前者, 只需要锁行
- 对于后者, 需要锁表
1 并发安全:SERIALIZABLE>REPEATABLE_READ>READ_COMMITTED
2 运行效率:READ_COMMITTED>REPEATABLE_READ>SERIALIZABLE
当不设置事务隔离级别将使用数据库的默认事务隔离级别:
#MYSQL:REPEATABLE‐READ
SELECT @@tx_isolation;
#ORACLE: READ_COMMITTED
SELECT s.sid, s.serial#,
CASE BITAND(t.flag, POWER(2, 28))
WHEN 0 THEN 'READ COMMITTED'
ELSE 'SERIALIZABLE'
END AS isolation_level
FROM v$transaction t
JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');