mysql事务隔离级别及实现原理,深度理解

1、事务是什么?

事务是数据库一个不可分的工作单元,可以将多个操作步骤表示为一个步骤。

2、事务的四大特性

Atomicity原子性, Consistency一致性,Isolation隔离性,Durability持久性

3、事务中出现的异常状况

脏读:一个事务读取到了另一个事务未提交的数据

时间  事务1  事务2
1   插入id=2数据
2  可以查询到id=2数据  
3   回滚事务,此时事务A查询到的id=2的数据就是脏数据

 

不可重复读

时间  事务1  事务2
1  查询id=2的数据,name值为张三  
2   update name=李四 where id=2
3   提交事务
4  查询id=2的数据,name值为李四  

 

幻读

当事务隔离级别为读已提交

时间  事务1  事务2
1  查询id>=1的数据,得到id为1,2的两条数据  
2   插入id=3,name=王五的数据
3   提交事务
4  再次查询id>=1的数据,得到id为1,2,3的三条数据  

 

当事务隔离级别为可重复读

时间  事务1  事务2
1  查询id>=1的数据,得到id为1,2的两条数据  
2   插入id=3,name=王五的数据
3   提交事务
4  执行 update tab set name = 王五1 where id = 3,此时update执行的是当前读,会更新id=3的快照数据  
5  再次查询id>=1的数据,得到id为1,2,3的三条数据  

 

4、锁介绍

  两阶段锁协议

    在InnoDB事务中,行锁是在用到的时候才加上的,但并不是不再用了就立刻释放,而是要等到事务commit或rollback才会释放

  锁的类型

    共享锁(shared lock)允许事务读一行数据

    排它锁(exclusive lock)允许事务删除或更新一行数据

  共享锁  排他锁
共享锁  兼容  不兼容
排它锁  不兼容  不兼容

  锁的算法

  行锁(record lock)针对单行记录的锁

  间隙锁(gap lock)锁定一个范围但不包含记录本身,注:在可重复读级别下存在

  间隙锁+行锁(Next-Key Lock)锁定一个范围并且包含记录本身,每个next-key lock都是前开后闭区间,假设数据库里有3条记录0,5,10 那么就有(-∞,0]、(0,5]、(5,10]、(10,+∞]4个可能的next-key lock,注:在可重复读、串行化级别下才存在

5、快照读与当前读

  多版本并发控制(MVCC):一行数据有多个版本,根据事务ID获取一致性读视图,数据版本相关内容维护在undo log里,注:在读已提交、可重复读级别下才存在,MVCC避免了锁的争抢,通过空间换时间保证了数据读取的正确性。

  快照读:读取的是快照数据,不保证是最新数据

  在读未提交、读已提交、可重复读隔离级别下,最普通的查询就是快照读

select * from table

  当前读:读到的数据是最新数据

-- 共享锁
select ... lock in share mode 
-- 排它锁
select ... for update 
insert ...
update ...
delete ...

6、事务隔离级别

  SQL标准定义了四个隔离级别

  • 读未提交(READ UNCOMMITED)

     特点:读的时候未对数据加锁,修改数据的时候对数据添加行级共享锁

          效果:因为修改数据时候添加的是共享锁,所以会被其他事务读到,产生脏读的问题

 

  • 读已提交(READ COMMIED)

      特点:(快照读)读的时候会通过MVCC的一致性视图读到最新的、已提交事务的数据版本

      效果:(快照读)因为通过MVCC读取的是已提交事务的数据版本,所以不会存在脏读。通过MVCC读到的数据,没有进行加锁操作, 所以其他事务仍然可以对读到的数据进行修改并提交,这时候再次读取就发生了不可重复读。

(当前读)通过显示加锁,防止了其他事务对其行数据的修改,从而避免了不可重复读

  • 可重复读(REPEATABLE READ)

     特点:(快照读)读的时候会通过MVCC的一致性视图读到开启事务时刻、已提交事务的最新数据版本

     效果:(快照读)因为通过MVCC读取的是开启事务时刻,已提交事务的数据版本,所以无论其他事务怎么修改,看到的数据都是雷打不动的固定的数据版本,这时候再次读取就避免了不可重复读。因为在修改数据的时候使用了next-key lock,所以即使进行插入操作也会被锁阻塞,这样也避免了幻读情况的产生。在实际情况中,锁的算法比较灵活 ,根据sql语句的不同,和命中索引的区别,即有next-key lock+gap lock锁住更大范围的情况,也有在唯一索引场景 next-key lock退化成 record lock以及gap lock的情况

  • 串行化(SERIALIZABLE)
  脏读  不可重复读  幻读
读未提交  未解决  未解决  未解决
读已提交  已解决  快照读未解决,可通过加锁解决  未解决
可重复读  已解决  已解决  MVCC能解决部分场景
串行化  已解决  已解决  已解决

  

 

posted @ 2023-02-16 09:25  西风51668  阅读(193)  评论(0)    收藏  举报