mysql事务底层与高可用原理

276 阅读6分钟

redo log(重做日志) 确保事务的持久性

redo log 是存储引擎层生成的日志,记录的是物理级别上的页修改操作,比如页号、偏移量、写入的数据。主要保证数据的可靠性

redo log 日志的好处

  1. redo日志降低了刷盘频率
  2. redo日志占用的空间非常小

存储表空间ID、页号、偏移量以及需要更新的值,所需的存储空间是很小的,刷盘快。

redo log 日志的特点

redo日志是顺序写入磁盘的

在执行事务的过程中,每执行一条语句,就可能产生若干条redo日志,这些日志是按照产生的顺序写入磁盘的,也就是使用顺序IO,效率比随机快。

事务执行过程中,redo日子不断记录

redo日志跟bin日志的区别,redo日志是存储引擎产生的,bin日志是数据库层产生的,假设一个事务,对表做了10万行的记录插入,这个过程中,一直不断的网redo日志顺序记录,而bin日志不记录,知道这个事务提交,才会一次性写入bin日志文件中

redo的组成

重做日志的缓冲

保存在内存中,易丢失。在服务器启动时就向操作系统申请了一大片称之为redo log buffer的连续内存空间,即redo日志缓冲区,这片内存空间被划分成若干连续的redo log block。一个redo log block 占用512字节大小。

image.png

重做日志文件

保存在硬盘,是持久的。 image.png

redo的整体提流程

image.png

  1. 先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝
  2. 生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值
  3. 当事务commit时,将redo log buffer中的内容刷新到 redo log file,对redo log file 采用追加写的方式
  4. 定期将内存中的修改的数据刷新到磁盘中

redo日志的刷盘策略

redo日志的写入并不是直接写入磁盘,InnoDB引擎在写redo日志的时候先写redo log buffer,之后以一定的频率刷入到真正的redo log file中。

image.png 注意:redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中区,只是刷入到文件系统缓存(page cache)中去,真正的写入会交给系统自己决定。那么对于InnoDB来说就存在一个问题,如果交给系统来同步,童谣如果系统宕机,那么数据也丢失了。 针对这种情况,InnoDB给出innodb_flush_log_at_trx_commit参数,该参数控制commit提交事务时,如何将redo log buffer中的日志刷新到redo log file中。三种策略:

  1. 设置为0:表示每次事务提交时不进行刷盘操作(系统默认master thread每隔1s进行一次重做日志的同步)
  2. 设置为1:表示每次事务提交时都将进行同步,刷盘操作(默认值)
  3. 设置为2:表示每次事务提交时都只把redo log buffer 内容写入page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。

image.png

image.png

image.png

undo log(回滚日志) 保证事务的原子性、一致性

undo log 是存储引擎层生成的日志.,记录的 是逻辑操作日志,比如对某一行数据进行了insert语句操作,那么undo log就记录一条阈值相反的delete操作,主要用于事务的回滚和一致性非锁定读。

undo日志的作用

回滚数据

MVCC

在InnoDB存储引擎中MVCC的实现是通过undo来完成的,当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的版本行信息,以此实现非锁定读。

undo的存储结构

回滚段与undo页

InnoDB对undo日志的管理采取段的方式,即回滚段,每个回滚段记录了1024个undo log segment,而在每个undo log segment段中进行undo页的申请。

  1. 在InnoDB1.1版本之前,只有一个rollback segment,因此支持同时在线的事务限制为1024,虽然对绝大多数的应用来说都已经够用。
  2. 从1.1版本开始InnoDB支持最大128个rollback segment,故其支持同时在先的事务限制提高了128*1024.

show variables like 'innodb_undo_logs'

  1. innodb_undo_directory:设置rollback segment文件所在的路径,这意味着rollback segment可以存放在共享表空间意外的位置,即可以设置为独立表空间。该参数的默认值为'./',表示当前InnoDB存储引擎的目录。
  2. innodb_undo_logs:设置rollback segment的个数,默认128.
  3. innodb_undo_tablespaces:设置构成rollback segment文件的数量,这样rollback segment可以较为平均的分布在文件中,设置该参数后,会在路径innodb_undo_directory看到undo为前缀的文件,该文件就会代表rollback segment文件。

undo页的重用

当我们开启一个事务需要写undo日志的时候,就得先去undo log segment中去找到一个空间的位置,当有空位的时候,就去申请undo页,在这个申请到的undo页中进行undo log的写入,我们知道mysql默认一页的大小时16k。

为每一个事务分配一个页,时非常浪费的,假设你的应用的TPS(每秒处理事务数目)为1000,那么1s就需要1000页,大概需要16M的存储,1分钟大概1G,很多空间浪费。

于是undo页就被设计的可以重用了,当食物提交时,并不会立刻删除undo页。因为重用,所以这个undo页可能混杂这其他事务 的undo log,undo log 在commit后,会 被放到一个链表中,然后判断undo页的使用空间是否小于3/4,如果小于3/4的话,则表示当前的undo页可以被重用,那么他就不会被回收,其他事务的undo log可以记录在但钱undo页的后面,由于undo log是离散的,所以清理对应的磁盘空间时,效率不高。

回滚段与事务

  1. 每个事务只会使用一个回滚段,一个回滚段在同一时刻可能会服务于多个事务
  2. 每一个事务开始的时候,会制定一个回滚段,在事务进行的过程中,当数据被修改时,原始的数据会被复制到回滚段。
  3. 在回滚段中,事务会不断填充盘区,知道事务结束或所有的空间被用完,如果但钱的盘区不够用,事务会在段中请求扩展一下盘区,如果所有已分配的盘区都被用完,事务会覆盖最初的盘区或者 在回滚段允许的情况下扩展新的盘区来使用。
  4. 回滚段存在于undo表空间中,在数据库中可以存在多个undo表空间,但同一时刻只能使用一个undo表空间。
  5. 事务提交时,InnoDB存储引擎会做一下两件事情
  6. 将undo log放入列表中,以供之后的purge操作
  7. 判断undo log所在的页是否可以重用,若可以分配给下个事务使用。

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png