Mysql的事务的实现原理

目录

 

1.事务的概念和目的

2 事务实现涉及的技术

2.1 redo log 与 undo log介绍

2.1.1 redo log

2.1.2 undo log

2.2 mysql锁技术

2.3 多版本并发控制

 3 总结


1.事务的概念和目的

概念:

事务就是一组原子性的SQL查询,或者说是独立的工作单元。

事务的ACID概念:原子性(Atomicity),一致性(Consistency),隔离型(Isolation)以及持久性(Durability)。

 

目的:

最终目的是保障数据的可靠性,一致性。

可靠性:数据库要保证当insert或update操作时抛异常或者数据库crash的时候需要保障数据的操作前后的一致,想要做到这点,需要知道修改之前和修改之后的状态,所以就有了undo log和redo log。

并发处理:当多个并发请求过来,并且其中有一个请求是对数据修改操作的时候会有影响,为了避免读到脏数据,所以需要对事务之间的读写进行隔离,具体使用哪个MySQL 的隔离级别,视业务场景而定。

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

  • READ UNCOMMITED (未提交读)
  • READ COMMITED (提交读)
  • REPEATABLE READ (可重复读)
  • SERIALIZABLE (可重复读)

2 事务实现涉及的技术

实现事务功能的三个技术如下:

  1. 日志文件(redo log 和 undo log)
  2. mysql锁技术
  3. 多版本并发控制MVCC(MultiVersion Concurrency Control)

2.1 redo log 与 undo log介绍

2.1.1 redo log

redo log叫做日重做日志,用于记录数据被修改后的信息以保证事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中。

作用:mysql 为了提升性能不会把每次的修改都实时同步到磁盘,而是会先存到Buffer Pool(缓冲池)里,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步。当未及时进行同步时,机器断电或宕机,会导致丢失部分的已提交事务的修改信息。因此引入redo log来记录已成功提交事务的修改信息,并且会把redo log持久化到磁盘,系统重启之后在读取redo log恢复最新数据。

MySQL的数据存储机制,MySQL的表数据是存放在磁盘上的,因此想要存取的时候都要经历磁盘IO,然而即使是使用SSD磁盘IO也是非常消耗性能的。

为此,为了提升性能InnoDB提供了缓冲池(Buffer Pool),Buffer Pool中包含了磁盘数据页的映射,可以当做缓存来使用:

读数据:会首先从缓冲池中读取,如果缓冲池中没有,则从磁盘读取在放入缓冲池;

写数据:会首先写入缓冲池,缓冲池中的数据会定期同步到磁盘中;

下面看下redo log是产生过程:

Mysql的事务的实现原理_第1张图片

start transaction;
select balance from bank where name="zhangsan";
// 生成 重做日志 balance=600
update bank set balance = balance - 400; 
// 生成 重做日志 amount=400
update finance set amount = amount + 400;
commit;

Mysql的事务的实现原理_第2张图片

 

2.1.2 undo log

undo log 叫做回滚日志,用于记录数据被修改前的信息以保证未提交事务的原子性。undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。

作用:undo log 记录事务修改之前版本的数据信息,因此假如由于系统错误或者rollback操作而回滚的话可以根据undo log的信息来进行回滚到没被修改前的状态。

假设有两个表 bank和finance,表中原始数据如图所示,当进行插入,删除以及更新操作时生成的undo log如下面图所示:

Mysql的事务的实现原理_第3张图片

Mysql的事务的实现原理_第4张图片

从上图可以了解到数据的变更都伴随着回滚日志的产生:

  1. 产生了被修改前数据(zhangsan,1000) 的回滚日志
  2. 产生了被修改前数据(zhangsan,0) 的回滚日志

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

根据undo log 进行回滚:

为了做到同时成功或者失败,当系统发生错误或者执行rollback操作时需要根据undo log 进行回滚。

Mysql的事务的实现原理_第5张图片

回滚操作就是要还原到原来的状态,undo log记录了数据被修改前的信息以及新增和被删除的数据信息,根据undo log生成回滚语句,比如:

  1. 如果在回滚日志里有新增数据记录,则生成删除该条的语句
  2. 如果在回滚日志里有删除数据记录,则生成生成该条的语句
  3. 如果在回滚日志里有修改数据记录,则生成修改到原先数据的语句

 

2.2 mysql锁技术

当有多个请求来读取表中的数据时可以不采取任何操作,但是多个请求里有读请求,又有修改请求时必须有一种措施来进行并发控制。不然很有可能会造成不一致。

为了解决上述问题,需要利用两种锁的组合来对读写请求进行控制,这两种锁被称为:

共享锁(shared lock),又叫做"读锁":读锁是可以共享的,或者说多个读请求可以共享一把锁读数据,不会造成阻塞。

排他锁(exclusive lock),又叫做"写锁":写锁会排斥其他所有获取锁的请求,一直阻塞,直到写入完成释放锁。

 

2.3 多版本并发控制

概念:InnoDB的 MVCC ,是通过在每行记录的后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存了行的过期时间,当然存储的并不是实际的时间值,而是系统版本号。主要实现思想是通过数据多版本来做到读写分离。从而实现不加锁读进而做到读写并行。

MVCC在mysql中的实现依赖的是undo log与read view

  • undo log :undo log 中记录某行数据的多个版本的数据。
  • read view :用来判断当前版本数据的可见性。

Mysql的事务的实现原理_第6张图片

 3 总结

实现事务采取了哪些技术以及思想?

  • 原子性:使用 undo log ,从而达到回滚;
  • 持久性:使用 redo log,从而达到故障后恢复;
  • 隔离性:使用锁以及MVCC,运用的优化思想有读写分离,读读并行,读写并行;
  • 一致性:通过回滚,以及恢复,和在并发环境下的隔离做到一致性。

参考来源:https://zhuanlan.zhihu.com/p/166256162

你可能感兴趣的:(MySQL学习)