mysql 事务设计原理深度解析

最近有同学面试被问到mysql事务设计原则,以及原理如何实现,我们经常说要熟悉mysql,不仅仅仅局限于相关语句的操作,还要对实现原理有一定深度的挖掘,为此,总结了这篇文章,供大家参考。更多信息,请关注微信公众号: 白白家族


一 事务管理设计原则

事务管理ACID是mysql设计事务需要遵守的原则,那么,mysql又是如何遵守实现的呢?

1>事务的原子性(A)是如何实现的?

利用 undo log 机制实现

2>事务的持久性(D)是如何实现的?

利用 redo log 机制实现

3>事务的隔离性(I)是如何实现的?

利用 读写锁+MVCC 来实现

4>事务的一致性(C)是如何实现的?

综合利用上述的原子性,持久性,隔离性来实现的


 

二 详细分析

1. 场景描述:

小明初始有100元余额,小红初始有0元,小明向小红转了100元红包。

语句实现:

update table set balance = balance - 100 where name=小明

update table set balance = balance +100 where name=小红

 

2. mysql原子性的实现

当mysql发生错误异常或者显式的执行rollback语句时,需要将数据回滚,也就是说,我们需要存储需要回滚前的数据情况,怎么去实现?通过undo log来实现。

mysql 事务设计原理深度解析

 

生成 undo log 流程如下:

>开启事务

>Update 操作 :

update table set balance = balance -100 where name=小明

>将记录A {info=(小明,100),type=update} 保存到 undo log中

>Update 操作:

update table set balance = balance +100 where name=小红

>将记录B {info=(小红,0,类型=update} 保存到undo log中

>事务提交/回滚

 

回滚数据流程如下:

根据记录A,将执行语句进行恢复

update table set balance = 100 where name=小明

根据记录B,将执行语句进行恢复

update table set balance = 0 where name=小红

 

综上所述:

1.每条数据变更(insert/update/delete)操作都伴随一条undo log的生成,并且回滚日志必须先于数据持久化到磁盘上 2.所谓的回滚就是根据回滚日志做逆向操作,比如delete的逆向操作为insert,insert的逆向操作为delete,update的逆向为update等。

 

 

3. mysql持久性的实现

事务一旦提交,数据将会保存到数据库中,如果此时系统崩溃,被修改的数据也不会丢失。那么我们该怎样实现呢?通过redo log,将提交事物的数据刷新到磁盘上,确保宕机不丢失数据.

mysql 事务设计原理深度解析

 

MySQL在做数据存储时,为了提升性能,InnoDB引入了缓冲池(Buffer Pool)机制。读数据时,首先会从缓冲池(buffer pool)中读取,如果没有,则从磁盘读取再放入buffer pool中;写数据时:首先会写入buffer pool,buffer pool中的数据会根据配置参数定期同步到磁盘中;

而 redo log, 就是在MySQL系统宕机,断电的时候,存储在buffer pool里,还没来得及在磁盘持久化,数据会丢失的情况下,提出的补救方案。

其中 redo log 的存储是顺序存储,而缓存同步是随机操作。顺寻存储的读写效率远远高于随机读写。

 

4. mysql隔离性的实现

当多个请求并发访问同一条数据的时候,mysql如何管理呢?所谓隔离性就是是要控制多个并发读写请求的访问顺序。

在SQL标准里定义了四种隔离级别,级别越低的隔离级别可以执行越高的并发,但同时实现复杂度以及开销也越大。

Mysql 隔离级别有以下四种(级别由低到高):

1> READ UNCOMMITED (未提交读)

2> READ COMMITED (提交读)

3> REPEATABLE READ (可重复读)

4> SERIALIZABLE (可重复读)

--- READ UNCOMMITTED

在该隔离级别下,事务A中的修改的数据即使还没提交,对事务B来说,A中修改的数据是可见的。事务可以读取未提交的数据,造成脏读,现实中不会用到采用这种级别。

 

--- READ COMMITTED

在该隔离级别下每次 select的时候新生成一个版本号,所以每次select的时候读的不是一个副本而是不同的副本。

在每次select之间有其他事务更新了我们读取的数据并提交了,那就出现了不可重复读

--- REPEATABLE READ

在该隔离级别下,同一个事务内的多次读取的结果是一样的,可以避免,脏读,不可重复读等查询问题。mysql有两种机制可以达到这种隔离级别的效果,分别是采用读写锁以及MVCC。

 

--- SERIALIZABLE

该隔离级别按照请求顺序依次执行,不存在并发情况,不会造成数据不一致问题,但是由于效率低下,一般生产环境不会用用

请关注微信公众号   白白家族

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值