• MySQl-事务日志


    目录

    一、redo日志

    1.1 优点与特点

    1.2 组成

    1.3 redo的流程

    1.4  redo log 的刷盘策略

    二、undo日志

    2.1 undo日志的作用

    2.2 undo的存储结构

    2.3  回滚段与事务

    2.4  undo的类型与生命周期

    三、总结


            事务的隔离性锁机制实现。

            而事务的原子性一致性持久性由事务的 redo 日志undo 日志来保证。它们在存储引擎层产生。

            REDO LOG 称为 重做日志 ,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性

            UNDO LOG 称为 回滚日志 ,回滚行记录到某个特定版本,用来保证事务的原子性一致性。 有的DBA或许会认为 UNDO 是 REDO 的逆过程,其实不然。

    一、redo日志

            事务包含 持久性 的特性,就是说对于一个已经提交的事务,在事务提交后即使系统发生了崩 溃,这个事务对数据库中所做的更改也不能丢失

            保证持久性的 一个简单的做法 :在事务提交完成之前把该事务所修改的所有页面刷新到磁盘,但是这个简单粗暴的做法有些问题:

            1.修改量可能跟刷新磁盘工作量严重不成比例。因为一个页面默认16KB,假设我们只改动了一个字节,那刷盘就需要刷新16KB的数据到磁盘,小题大做。

            2.随机IO刷新慢,事务所修改的页面可能并不相邻,直接刷盘会产生很多随机IO

            另一个解决的思路 :我们只是想让已经提交了的事务对数据库中数据所做的修改永久生效,即使后来系统崩溃,在重启后也能把这种修改恢复出来。所以我们其实没有必要在每次事务提交时就把该事务在内存中修改过的全部页面刷新磁盘,只需要把 修改 了哪些东西 记录一下 就好。

    1.1 优点与特点

            redo日志降低刷盘频率

            redo日志占用的空间非常小

            redo日志是顺序写入磁盘的

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

    1.2 组成

            可分为两部分:

            1.重做日志缓冲(redo log buffer),保存在内存中。

            服务器启动时会申请一大片连续内存空间,就是redo日志的缓冲区,这片空间又被分成若干block,每个占用512字节的大小。

             redo log buffer 大小:默认 16M ,最大值是4096M,最小值为1M。

            参数设置:innodb_log_buffer_size

            2.重做日志文件(redo log file),保存在硬盘中,是持久的。

    1.3 redo的流程

             以一个更新事务为例,redo log 流转过程,如下图所示:

    第1步:先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝

    第2步:生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值

    第3步:当事务commit时,将redo log buffer中的内容刷新redo log file,对 redo log file采用追加写的方式

    第4步:定期内存中修改的数据刷新磁盘

            在持久化一个数据页之前,先将内存中相应的日志页持久化。

    1.4  redo log 的刷盘策略

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

            注意,redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中去,只是刷入到 文件系统缓存 (page cache)中去(这是现代操作系统为了提高文件写入效率做的一个优化),真正的写入会交给OS自己来决定(比如page cache足够大了)。

             InnoDB给出 innodb_flush_log_at_trx_commit 参数,该参数控制 commit提交事务时,如何将 redo log buffer 中的日志刷新到 redo log file 中。它支持三种策略

    设置为0 :表示每次事务提交时不进行刷盘操作。(系统默认master thread每隔1s进行一次重做日志的同步)

    设置为1 :表示每次事务提交时都将进行同步,刷盘操作( 默认值 )

    设置为2 :表示每次事务提交时都只把 redo log buffer 内容写入 page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。

             如果日志满了怎么办?

             采用循环使用的方式向redo日志文件组里写数据会导致后写入的redo日志覆盖掉前边写的redo日志,所以InnoDB的设计者提出了checkpoint的概念。

             如果 write pos 追上 checkpoint ,表示日志文件组满了,这时候不能再写入新的 redo log记录,MySQL 得停下来,清空一些记录,把 checkpoint 推进一下。

    二、undo日志

            redo log是事务持久性的保证,undo log是事务原子性的保证。在事务中 更新数据前置操作 其实是要 先写入一个 undo log

            事务需要保证 原子性 ,也就是事务中的操作要么全部完成,要么什么也不做。但有时候事务执行到一半会出现一些情况,比如:

            情况一:事务执行过程中可能遇到各种错误,比如服务器本身的错误,操作系统错误 ,甚至是突然断电导致的错误。

            情况二:程序员可以在事务执行过程中手动输入 ROLLBACK 语句结束当前事务的执行。

            以上情况出现,我们需要把数据改回原先的样子,这个过程称之为 回滚 ,这样就可以造成一个假象:这个事务看起来什么都没做,所以符合 原子性 要求。

    2.1 undo日志的作用

            作用1:回滚数据

             undo并不是将数据库物理地恢复到原来的样子,它是逻辑日志,只是将数据库逻辑地恢复到原来的样子,但数据结构页本身可能已经被改变了。

            作用2:MVCC

            innoDB中地MVCC是通过undo来完成的。当用户读取一条行记录时,如果记录已经被其他事务占用当前事务可以通过undo读取之前行版本信息,实现非锁定读取

    2.2 undo的存储结构

            InnoDBundo log的管理采用的方式,也就是 回滚段(rollback segment)

            每个回滚段记录了 1024undo log segment ,而在每个undo log segment段中进行 undo页申请。 在 InnoDB1.1版本之前 (不包括1.1版本),只有一个rollback segment,因此支持同时在线的事务 限制为 1024 。虽然对绝大多数的应用来说都已经够用。 从1.1版本开始InnoDB支持最大 128rollback segment ,故其支持同时在线的事务限制提高到 了 128*1024 。

            undo页的重用

            当开启一个事务需要写undo log 时,要先去undo log segment中申请空闲位置,当有空位的时候申请undo页,在undo页中进行undo log写入。如果为每一个事务都分配一个页将会是非常浪费的,于是undo页就被设计为可重用的,当事务提交时并不会立刻删除undo页,这个undo页可能混杂着其他事务undo logundo log在事务提交之后会放入一个链表中,然后判断undo页的使用是否超过3/4,没有超过的话就表示该可以重用,暂时不会被回收其他事务的undo log可以记录在当前undo页后面。undo log是离散的。

    2.3  回滚段与事务

            1. 每个事务只会使用一个回滚段一个回滚段在同一时刻可能会服务于多个事务

            2. 当一个事务开始的时候,会制定一个回滚段,在事务进行的过程中,当数据被修改时,原始数据会被复制回滚段。        

            3. 在回滚段中,事务会不断填充盘区,直到事务结束或所有的空间被用完。如果当前的盘区不够用,事务会在段中请求扩展下一个盘区,如果所有已分配的盘区都被用完,事务会覆盖最初的盘区或者在回滚段允许的情况下扩展新的盘区来使用。

            4. 回滚段存在于undo表空间中,在数据库中可以存在多个undo表空间,但同一时刻只能使用一个 undo表空间

            5. 当事务提交时,InnoDB存储引擎会做以下两件事情:

                    将undo log放入列表中,以供之后的清除操作

                    判断undo log所在的页是否可以重用,若可以分配给下个事务使用

            回滚段中的数据分类

            1. 未提交的回滚数据(uncommitted undo information)-不能被其他事务的数据覆盖

            2. 已经提交但未过期的回滚数据(committed undo information)

                    -过期之前不能被其他事务的数据覆盖

            3. 事务已经提交并过期的数据(expired undo information)-会被优先覆盖掉

    2.4  undo的类型与生命周期

             在InnoDB存储引擎中,undo log分为:

                    insert undo log-插入操作产生的undo log,事务提交之后就删除

                    update undo log-更新、删除操作产生的undo log,它可能需要提供MVCC机制,所以提交后放入链表中,等待purge线程来删除,不会立刻删除

            undo log的生命周期

             在更新Buffer Pool中的数据之前,我们需要先将该事务开始之前的状态写入undo log中。假设更新到一半出错了,我们就可以通过undo log回滚事务开始前的状态

            undo log 的详细生成与回滚过程

            对于InnoDb引擎,每个行记录有这样两个隐藏列事务ID回滚指针(指向undo log)。

             当我们插入一条数据时,会生成一条undo log,回滚指针指向它。

             接着更新“姓名”字段,会再生成一条新的undo log,回滚指针指向新的undo log,新的undo log指向旧的。

             假如我们再改变主键值,此时会把原来数据的deletemark标志打开,但并没有真正删除数据。然后在后面插入一条新数据,新数据也会产生undo log。

            每次对数据的更改都会产生一个undo log,且序号是递增的

            回滚时按照序号依次向前推就能找到原始数据

    三、总结

            undo log是逻辑日志,对事务回滚时,只是将数据库逻辑地恢复到原来的样子。

            redo log是物理日志,记录的是数据页物理变化,undo log不是redo log的逆过程

  • 相关阅读:
    Flutter高仿微信-第52篇-群聊-清空聊天记录
    K8S - Pod 的概念和简介
    cube开源一站式云原生机器学习平台--volcano 多机分布式计算
    VS“无法查找或打开PDB文件”问题
    Na小工具(电脑)
    Java:性能优化细节31-45
    MATLAB | 绘图复刻(三) | 分层聚类分析图:树状图+热图
    LeetCode //C - 148. Sort List
    【无标题】
    20个Python random模块的代码示例
  • 原文地址:https://blog.csdn.net/weixin_62427168/article/details/125614573