Mysql 事务

2021-07-26  本文已影响0人  Ethan_zyc

事务的ACID

事务隔离级别

读未提交

image

读已提交

同一个事务中读到读两次结果不一样,所以也叫不可重复读


image

可重复读

事务A永远读到的是事务刚开始时候的数据


image

串行化

image

串行化会对表或者表中的目标行加锁,具体实现根据存储引擎来定
Innodb中的事务隔离级别和锁的关系

补充:幻读

这不是隔离级别,只是一个会出现的问题,串行化可以解决幻读


image

Mysql 怎么保证可重复读

回顾一下刚刚的图,明明事务B已经修改了name,那么事务A读的时候李四这个数据是存储在哪边的?

这就引发出MVCC机制,就是多版本并发控制 multi-version concurrency control

innodb存储引擎,会在每行数据的最后加两个隐藏列,一个保存行的创建时间,一个保存行的删除时间,但是这儿存放的不是时间,而是事务id,事务id是mysql自己维护的自增的,全局唯一。

把上图的过程用来举个例子:
事务A的事务id为1
事务B的事务id为2

step1

查询id=1,得到name=李四

id name 创建时间 删除时间创建事务id <= 当前事务id,当前事务id < 删除事务id
1 李四 1 null

step2

将id=1的name改成张三,事务还未提交

id name 创建时间 删除时间
1 李四 1 null
1 张三 2 null

step3

事务id=1的事务,查询id=1的这一行的时候,一定会找到创建事务id <= 当前事务id的那一行,select * from table where id=1,就可以查到李四的那一行

补充 step4

假如事务C(事务id=3)这时候删除了李四,那么删除时间就是3

id name 创建时间 删除时间
1 李四 1 3
1 张三 2 null

事务A查询id=1还是能查到name=4,因为查询的是

事务传播级别

场景:方法A使用了 @Transactional 注解,方法B也使用了 @Transactional 注解,方法A调用了方法B,这时候就需要考虑事务传播级别。

PROPAGATION_REQUIRED

默认传播级别
B不会单独开事务,直接使用A的事务

PROPAGATION_SUPPORTS

如果B使用了该传播级别,假如A加了 @Transactional 注解,那么B使用A的事务,如果A没有加 @Transactional 注解,那么B自己也不开事务

PROPAGATION_MANDATORY

必须被开启了事务的方法调用,不然就报错

PROPAGATION_REQUIRES_NEW

强制自己开一个新的事务,假如事务B使用该隔离级别,如果A调用B的地方try catch了,那么A方法就不会回滚,B会回滚

PROPAGATION_NOT_SUPPORTED

使用了该隔离级别的方法不会加入到事务中,报错也不会回滚

PROPAGATION_NEVER

不能会开启了事务的方法调用

PROPAGATION_NESTED

开启子事务,B会回滚到开启子事务的save point

上一篇下一篇

猜你喜欢

热点阅读