深入理解MySQL底层事务隔离级别的实现原理

2021-10-25 10:40:40 浏览数 (1)

MySQL事务的四大隔离级别

为了解决并发事务存在的脏读、不可重复读、幻读等问题,数据库大叔设计了四种隔离级别。分别是读未提交,读已提交,可重复读,串行化(Serializable)。

01

读未提交

读未提交隔离级别,只限制了两个数据不能同时修改,但是修改数据的时候,即使事务未提交,都是可以被别的事务读取到的,这级别的事务隔离有脏读、重复读、幻读的问题。

02

读已提交

读已提交隔离级别,当前事务只能读取到其他事务提交的数据,所以这种事务的隔离级别解决了脏读问题,但还是会存在重复读、幻读问题。

03

可重复读

可重复读隔离级别,限制了读取数据的时候,不可以进行修改,所以解决了重复读的问题,但是读取范围数据的时候,是可以插入数据,所以还会存在幻读问题。

04

串行化

事务最高的隔离级别,在该级别下,所有事务都是进行串行化顺序执行的。可以避免脏读、不可重复读与幻读所有并发问题。但是这种事务隔离级别下,事务执行很耗性能。

1

四大隔离级别,都会存在哪些并发问题呢?

1

数据库是如何保证事务的隔离性的呢?

数据库是通过加锁,来实现事务的隔离性的。

这就好像,如果你想一个人静静,不被别人打扰,你就可以在房门上加上一把锁。

加锁确实好使,可以保证隔离性。

比如串行化隔离级别就是加锁实现的

但是频繁的加锁,导致读数据时,没办法修改,修改数据时,没办法读取,大大降低了数据库性能

那么,如何解决加锁后的性能问题的?

答案就是,MVCC多版本并发控制

它实现读取数据不用加锁,可以让读取数据同时修改。修改数据时同时可读取。

什么是MVCC?

MVCC实现的关键知识点

01

事务版本号

事务每次开启前,都会从数据库获得一个自增长的事务ID,可以从事务ID判断事务的执行先后顺序。这就是事务版本号。

02

隐式字段

对于InnoDB存储引擎,每一行记录都有两个隐藏列trx_id、roll_pointer,如果表中没有主键和非NULL唯一键时,则还会有第三个隐藏的主键列row_id。

03

undo log

undo log,回滚日志,用于记录数据被修改前的信息。在表记录修改之前,会先把数据拷贝到undo log里,如果事务回滚,即可以通过undo log来还原数据。

04

版本链

多个事务并行操作某一行数据时,不同事务对该行数据的修改会产生多个版本,然后通过回滚指针(roll_pointer),连成一个链表,这个链表就称为版本链。如下:

05

快照读和当前读

06

Read View

MVCC实现原理分析

1

查询一条记录,基于MVCC,是怎样的流程

  • 获取事务自己的版本号,即事务ID
  • 获取Read View
  • 查询得到的数据,然后Read View中的事务版本号进行比较。
  • 如果不符合Read View的可见性规则, 即就需要Undo log中历史快照;
  • 最后返回符合规则的数据
  • InnoDB 实现MVCC,是通过

Read View Undo Log

  • 实现的,Undo Log 保存了历史快照,Read View可见性规则帮助判断当前版本的数据是否可见。

1

读已提交(RC)隔离级别,存在不可重复读问题的分析历程

1

可重复读(RR)隔离级别,解决不可重复读问题的分析

其实,上图事务A中,多加了update account set balance=200 where id=5;这步操作,同一个事务,相同的sql,查出的结果集不同了,这个结果,就符合了幻读的定义~

0 人点赞