1 mysql事务隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
未提交读(Read uncommitted) | √ | √ | √ |
已提交读(Read committed) | × | √ | √ |
可重复读(Repeatable read) | × | × | √ |
可串行化(Serializable ) | × | × | × |
-
未提交读(Read Uncommitted):脏读(读取未提交数据)
B给A转100块钱 ,A查询发现到账100 ,B发现错误,回滚数据,实际A未拿到那100
-
提交读(Read Committed):不可重复读(前后多次读取,数据内容不一致)
A查询账户有100元 同时B 取走了A里面50元,A再查询账户只有50元
-
可重复读(Repeated Read):幻读(前后多次读取,数据总量不一致)
B查A账户有100元准备想取出来 ,同时A在消费 用了50元,B发现看到是100却取出100失败
-
串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
乐观锁 &悲观锁
乐观锁
更新语句中增加过滤条件,进行版本的判断
begin;
select name,realname,utime from account where name='aaak';
aaak ak 2018-06-12 18:20:06
update account set utime =123123 where name='aaak' and realname='aaak ';
commit;
悲观锁
悲观锁的特点是先获取锁,再进行业务操作 通常用select … for update操作来实现悲观锁
BEGIN;
SELECT * FROM account where id = 1 FOR UPDATE;
UPDATE account set `realname` = "aak" where id = 1;
MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。
因为InnoDB对于行的查询都是采用了Next-Key
Lock的算法,锁定的不是单个值,而是一个范围,按照这个方法是会和第一次测试结果一样。但是,当查询的索引含有唯一属性的时候,Next-Key
Lock 会进行优化,将其降级为Record Lock,即仅锁住索引本身,不是范围。
2 spring事务传播机制和隔离级别
1 spring事务传播机制
类型 | 解释 |
---|---|
REQUIRED | 1支持当前事务,如果当前没有事务,则新建事务 2如果当前存在事务,则加入当前事务,合并成一个事务 |
REQUIRES_NEW | 1新建事务,如果当前存在事务,则把当前事务挂起 2这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交 |
NESTED | 1如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交 2如果当前没有事务,则新建事务 3如果它异常,父级可以捕获它的异常而不进行回滚,正常提交 4但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别 |
SUPPORTS | 1如果当前存在事务,则加入事务 2如果当前不存在事务,则以非事务方式运行,这个和不写没区别 |
NOT_SUPPORTED | 1以非事务方式运行 2如果当前存在事务,则把当前事务挂起 |
MANDATORY | 1如果当前存在事务,则运行在当前事务中 2如果当前无事务,则抛出异常,也即父级方法必须有事务 |
NEVER | 1以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务 |
一般用得比较多的是 PROPAGATION_REQUIRED , REQUIRES_NEW;
REQUIRES_NEW 如果save()中的代码抛出异常,并且被捕获,commit()中的其他代码不会roll back ,如果其他代码抛出异常,而且没有捕获,不会导致save()回滚
2隔离级别
数据库是可以控制事务的传播和隔离级别的,Spring在之上又进一步进行了封装,可以在不同的项目、不同的操作中再次对事务的传播行为和隔离级别进行策略控制。
- Spring会在事务开始时,根据你程序中设置的隔离级别,调整数据库隔离级别与你的设置一致。
- 当使用Serializable级别时,Mysql在执行SQL时会自动修改为select … lock in share mode, 即使用共享锁。此时允许同时读,但只允许一个事务写,且锁的是行而不是整张表。
- 如果数据库不支持某种隔离级别,那么Spring设置了也无效。
- 当使用Serializable级别时,如果两个事务读写的不是同一行,那么它们是互不影响的。如果操作同一行记录,那么允许同时读,但如果出现一个对此行的写操作,则在写事务没有提交之前,所有的读事务都会被block。
参考:
MySQL 之 InnoDB引擎 Transaction
Spring事务管理与数据库隔离级别的关系
MySQL事务隔离级别和Spring事务关系介绍
Spring事务隔离级别与Mysql InnoDB事务隔离级别的关系