问题背景:
最近在学习Spring的事务部分,其中涉及到了Spring事务属性的配置,其中一个isolation把我整懵逼了
isolation设置事务的隔离级别
- DEFAULT :默认隔离级别, 会采用数据库的隔离级别
- READ_UNCOMMITTED : 读未提交
- READ_COMMITTED : 读已提交
- REPEATABLE_READ : 重复读取
- SERIALIZABLE: 串行化
"isolation"这个单词好像还见过,下面这一堆大写的洋文我就不知道了
经过一番搜查,整理了相关资料写出这第一篇稍微比原来专业的文章
还请多建议、多指正
事务的特性(ACID)
首先我们来复习一下经典的ACID
要实现事务的最终目的,需要几种机制组合才能实现,这几种机制就是事务的几个特性,分别是原子性、隔离性、一致性、持久性。用一句话总结来总结这几个特性之间的关系,那就是“一致性是事务的最终目的,而原子性、隔离性、持久性其实都是为了实现一致性的手段”。
1、原子性(Atomicity)
概念:一个事务必须是一系列操作的最小单元,这系列操作的过程中,要么整个执行,要么整个回滚,不存在只执行了其中某一个或者某几个步骤。
对应到上面的转账操作中,原子性就代表(检查余额、转账、到账)三个步骤就是一个整体,少了任何一个都不能称为一次转账,整个过程中检查余额、转账、到账要么整体都执行,要么一个失败就整体失败,绝对不会出现某一个执行成功其他的都执行失败,或者某一个执行失败其他的操作执行成功的情况。
2、隔离性(Isolation)
概念:隔离性是说两个事务的执行都是独立隔离开来的,事务之前不会相互影响,多个事务操作一个对象时会以串行等待的方式保证事务相互之间是隔离的:
小明和小芳各自有一本作业本,如果他们同时去写作业,这时他们都可以在各自作业本上写作业是相互不影响的。但是如果他们两个人只有一本作业本,但是他们都想去写作业怎么办,那么这个时候就只能等一个人先写完作业后,另外一个人才能写,要不然两个人同时在同一个作业本上写作业,那么肯定会乱套。所以这种两个事物操作同一个对象必须隔离开来不能相互影响的特性称为事务的隔离性。
3、一致性(Consistency)
概念:事务要保证数据库整体数据的完整性和业务数据的一致性,事务成功提交整体数据修改,事务错误则回滚到数据回到原来的状态。
如上面转账的案例,如果事务提交成功则A账户减金额,B账户则加对应的金额,数据库总体金额不变只是载体变了。如果事务出错则整体回滚,无论到了上面的哪个步骤A和B的数据都会回到事务开启前的状态保证数据的始终一致。
4、D(Durability)持久性:
概念:持久性是指一旦事务成功提交后,只要修改的数据都会进行持久化(通常是指数据成功保存到磁盘),不会因为异常、宕机而造成数据错误或丢失。
探究隔离性(Isolation):
JDBC为了解决隔离性问题制定了事务隔离级别(Transaction Isolation Level)规范。即:
隔离级别共四个级别:
从上往下,级别越来越高,并发性越来越差,安全性越来越高
Read uncommitted(读未提交 )
Read committed(读提交)
Repeatable read(重复读)(Mysql默认隔离级别)
Serializable(序列化:最高级别的事务隔离,花费高,性能低,一般很少用)
这四个级别即为上文提到的大写洋文,具体的解释如下
(1)读未提交(read Uncommited): 在该隔离级别,所有的事务都可以读取到别的事务中未提交的数据,会产生脏读问题,在项 目中基本不怎么用, 安全性太差;
脏读 (事务修改数据没提交,另一个事物提前读取):脏读就是指当一个事务正在访问数据,并且对数据进行了修改,
而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
(2) 读已提交(read commited): 这是大多数数据库默认的隔离级别,但是不是 MySQL 的默认隔离级别;这个隔离级别满足 了简单的隔离要求:一个事务只能看见已经提交事务所做的改变,所以会避免脏读问题;
但由于一个事务可以看到别的事务已经提交的数据,于是随之而来产生了不可重复读和幻读等问题;
不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。
那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。
这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
(3) 可重复读(Repeatable read): 这是 MySQL 的默认隔离级别,它确保了一个事务中多个实例在并发读取数据的时候会读取到一样的数据;
不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。
简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当 用户再读取该范围的数据行时,
会发现有新的“幻” 行。
InnoDB 和 Falcon 存储引擎通 过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
(4) 可串行化(serializable): 事物的最高级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之, 它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争,一 般为了提升程序的吞吐量不会采用这个;