UNDO特性:避免脏读、事务回滚、非阻塞读、MVCC、崩溃恢复

崩溃恢复:redo前滚、undo回滚

长事务、大事务:危害、判断、处理

UNDO优化:实现undo分离、收缩undo表空间

0、undo物理存储研究

1>ibdata第五个数据块(系统事务表)中存储着128个undo段的段头块的地址

2>每一个undo段头块有1024行,两行记录一个事务,一共可以记录512个事务

3>一个数据行中存放XID、rollpointr

4>一个数据行被修改

1.新的事务ID

2.新的rollpointr

3.修改后数据

上面三部分数据都会进入到回滚块中。详细见:事务工作流程……

一、UNDO特性

1、避免脏读

1>在操作任何数据之前,首先将数据备份到undo页中,然后再进行数据的修改;

2>不能看到其他会话未提交的数据;

3>当要读取被修改数据页数据行时,会指向备份在undo页中的数据,而避免脏读。

2、事务的回滚

undo最基本的作用是rollback,旧数据先放到undo里面存放,等rollback时候再将undo里面的数据回滚回来。

3、DML不阻塞读

提高并发,如果别的用户正在修改某数据页,事务没有提交,现需要读该数据页,发现事务没有提交,就根据数据行上的rollpointer找到原来的数据(在undo页上),结合该数据页将数据返给用户。

4、MVCC(一致性读)

多版本控制Multiversion Concurrency Control

5、崩溃恢复(回滚)

自动回滚未提交事务;

redo前滚,undo回滚,未提交事务主动回滚,未提交事务信息在事务槽里写着。数据库在运行期间,突然崩了,数据库启动之后,需要redo前滚,就会有很多未提交的事务(事务的会话断了,不可能继续完成了,就需要对未提交事务回滚了 )也滚回来了:读取未提交事务事务槽信息,把未提交事务回滚。

二、事务工作流程:存储结构

1、分配一个事务ID,事务ID依次递增

2、分配一个事务槽,将事务信息写入事务槽中

3、开始修改数据行,数据行中存储事务ID、修改前数据所使用的回滚块地址

4、回滚块中存放修改前的数据

5、属于一个事务的各个回滚块链接起来

6、回滚段段头块中的地址指向回滚块链表中的最后一个回滚块

7、一个回滚块只能存放一个事务的数据

8、事务提交就是在事务槽中将事务状态改成已提交

三、MVCC原理机制

理解不深(转自:http://www.cnblogs.com/chenpingzhao/p/5065316.html)

1、MVCC的几个特点:

1>每行数据都存在一个版本,每次数据更新时都更新该版本

2>修改时Copy出当前版本随意修改,各个事务之间无干扰

3>保存时比较版本号,如果成功(commit),则覆盖原记录;失败则放弃copy(rollback)

也就是每行都有版本号,保存时根据版本号决定是否成功,听起来含有乐观锁的味道;

2、非阻塞读Innodb的实现方式:

4>事务以排他锁的形式修改原始数据

5>把修改前的数据存放于undo log,通过回滚指针与主数据关联

6>修改成功(commit)啥都不做,失败则恢复undo log中的数据(rollback)

3、区别理解

二者最本质的区别是,当修改数据时是否要排他锁定;

Innodb的实现真算不上MVCC,因为并没有实现核心的多版本共存,undo log中的内容只是串行化的结果,记录了多个事务的过程,不属于多版本共存。但理想的MVCC是难以实现的,当事务仅修改一行记录使用理想的MVCC模式是没有问题的,可以通过比较版本号进行回滚;但当事务影响到多行数据时,理想的MVCC据无能为力了。

比如,如果Transaciton1执行理想的MVCC,修改Row1成功,而修改Row2失败,此时需要回滚Row1,但因为Row1没有被锁定,其数据可能又被Transaction2所修改,如果此时回滚Row1的内容,则会破坏Transaction2的修改结果,导致Transaction2违反ACID。

理想MVCC难以实现的根本原因在于企图通过乐观锁代替二段提交。修改两行数据,但为了保证其一致性,与修改两个分布式系统中的数据并无区别,而二提交是目前这种场景保证一致性的唯一手段。二段提交的本质是锁定,乐观锁的本质是消除锁定,二者矛盾,故理想的MVCC难以真正在实际中被应用,Innodb只是借了MVCC这个名字,提供了读的非阻塞而已。

四、崩溃恢复

redo前滚、undo回滚……

1、两个保证

1>数据库保证所有已提交事务的redolog都写入到了redo logfile中

2>数据库保证所有脏块的redolog都早redo logfile中,只有脏块写入磁盘以后,redo log才能被覆盖

结论:redo log有足够的能力将该有的脏块都构造出来

2、redo log如何确定使用哪些日志来构造脏块

1>起点:checkpoint开始

1.innodb buffer pool中存在一条flush list链表

2.这个链表最旧的那一端对应的redo log就是将来数据库崩溃恢复redolog前滚的起点

3.clean线程周期性的将需要flush list最旧的那一个脏块对应的redo log地址写入到ibdata中

2>终点:redo log current最后一条日志

3、崩溃恢复的过程

第一个阶段是前滚:

前滚对应的redo log的启动和终点已经确定:redolog不害怕多跑,因为redolog有版本,数据块有版本,如果redolog比数据块还要旧,就采用空跑的方式

第二个阶段是回滚:

崩溃时没有提交的事务也会被回滚回来,这些事务都属于死事务,因为这些事务对应的用户会话已经结束,后续读到对应的数据块,发现数据块上有未提交事务,读取未提交事务对应的事务信息,发现已经是死事务,主动回滚这个数据块;

碰到死事务对应的数据块,谁使用谁回滚。

五、大事务、长事务

1、长事务的危害

开始一个事务,长时间不提交,所有的数据都需要undo去保存,可能产生很多undo数据,而且还不能被清空覆盖,一直保存到该事务提交。很严重。

2、大事务的危害

修改批量的数据,占用过多的undo页(产生undo数据主要是delete产生的,但MySQL对delete做了优化,添加deleted_flag标志位,减少delete对undo的使用),所以危害不是很大,而且正常的事务场景也不会出现大事务。

3、如何判断大事务和长事务

mysql> desc information_schema.INNODB_TRX;

关键参数:

1.trx_started:事务开始的时间,如果时间较当前差很远说明是长事务

2.trx_rows_modified:事务修改的行数量,如果值很大说明是大事务

3.trx_mysql_thread_id:该事务所对应的线程id(kill线程清理事务)

4、解决棘手的大事务、长事务

处理大事务:kill -9 mysql_process_id:处理大事务,就直接干掉mysql实例,不会主动去回滚所以速度块,然后重启。(除非迫不得已,否则不那么干,生产环境重启服务器是天大的事情)

处理长事务:如果开始的时间不是很长,并且行数不是很多,直接kill掉该事务所在的线程。(在数据库里kill,可能反应慢)

六、UNDO的优化处理

1、实现undo分离

在MySQL5.5以及之前,除了数据量自然增长之外,一旦出现大事务,其所使用的undo log占用的空间就会一直在ibdata1里面存在,即使这个事务已经关闭。随着数据库上线时间越来越长,ibdata1文件会越来越大,物理备份文件越来越大……

MySQL 5.6增加了如下参数,可以把undo log从ibdata1移出来单独存放。

mysql> show variables like '%undo%';

+--------------------------+------------+

| Variable_name | Value |

+--------------------------+------------+

| innodb_max_undo_log_size | 1073741824 |

| innodb_undo_directory | ./ |

| innodb_undo_log_truncate | ON |

| innodb_undo_logs | 128 |

| innodb_undo_tablespaces | 3 |

+--------------------------+------------+

5 rows in set, 1 warning (0.00 sec)

1> innodb_undo_directory:

指定单独存放undo表空间的目录,默认为.(即datadir),可以设置相对路径或者绝对路径。该参数实例初始化之后虽然不可直接改动,但是可以通过先停库,修改配置文件,然后移动undo表空间文件的方式去修改该参数;

2> innodb_undo_tablespaces:

指定单独存放的undo表空间个数,例如如果设置为3,则undo表空间为undo001、undo002、undo003,每个文件初始大小默认为10M。该参数实例初始化之后不可改动;

3> innodb_undo_logs:

指定回滚段的个数(早期版本该参数名字是innodb_rollback_segments),默认128个。每个回滚段可同时支持1024个在线事务。这些回滚段会平均分布到各个undo表空间中。该变量可以动态调整,但是物理上的回滚段不会减少,只是会控制用到的回滚段的个数。

操作undo分离:实际使用方面,在初始化实例之前,我们只需要设置innodb_undo_tablespaces参数(建议大于等于3)即可将undo log设置到单独的undo表空间中。

2、在线收缩undo表空间

MySQL 5.7引入了新的参数,innodb_undo_log_truncate,开启后可在线收缩拆分出来的undo表空间,支持动态设置。

1>实现在线收缩undo的条件

1.innodb_undo_tablespaces>=2:因为truncate undo表空间时,该文件处于inactive状态,如果只有1个undo表空间,那么整个系统在此过程中将处于不可用状态;

2.innodb_undo_logs>=35(默认128):因为在MySQL 5.7中,第一个undo log永远在共享表空间中,另外32个undo log分配给了临时表空间(即ibtmp1),至少还有2个undo log才能保证2个undo表空间中每个里面至少有1个undo log;

2>满足以上2个条件后

innodb_undo_log_truncate=ON,即可开启undo表空间的自动truncate

1.innodb_max_undo_log_size:undo表空间文件超过此值即标记为可收缩,默认1G,truncate之后空间缩小到10M;

2.innodb_purge_rseg_truncate_frequency:指定purge操作被唤起多少次之后才释放rollback segments。当undo表空间里面的rollback segments被释放时,undo表空间才会被truncate。(最大是128,最小是1,默认为128)该参数越小,undo表空间被尝试truncate的频率越高。

mysql undo001_MySQL之UNDO及MVCC、崩溃恢复相关推荐

  1. mysql停止修复_浅析MySQL 8.0崩溃恢复

    本文将结合MySQL 8.0.19 分析InnoDB崩溃恢复的拉起过程,包括恢复前的准备工作,redo回放,undo回滚,以及崩溃恢复后Crash Safe DDL的实现.其中重点介绍redo的回放. ...

  2. 原创 MySQL探秘(八):基于Redo Log和Undo Log的MySQL崩溃恢复流程(一致性)

    黑盒下的更新数据流程 当我们查询数据的时候,会先去Buffer Pool中查询.如果Buffer Pool中不存在,存储引擎会先将数据从磁盘加载到Buffer Pool中,然后将数据返回给客户端:同理 ...

  3. mysql 崩溃恢复_超详细的MySQL数据库InnoDB崩溃恢复机制总结

    概述 数据库系统与文件系统大的区别在于数据库能保证操作的原子性,一个操作要么不做要么都做,即使在数据库宕机的情况下,也不会出现操作一半的情况,这个就需要数据库的日志和一套完善的崩溃恢复机制来保证.下面 ...

  4. mysql崩溃恢复过程_一起看下MySQL的崩溃恢复到底是怎么回事

    思考一个问题 为什么在你当update时,事物提交之前先不断的写redo log呢? 如果你看过白日梦前面介绍buffer pool的文章,这个问题的答案想必你也能很快的想出来:MySQL为了提高性能 ...

  5. MySQL · 引擎特性 · InnoDB 崩溃恢复过程

    在前面两期月报中,我们详细介绍了 InnoDB redo log 和 undo log 的相关知识,本文将介绍 InnoDB 在崩溃恢复时的主要流程. 本文代码分析基于 MySQL 5.7.7-RC ...

  6. MySQL 崩溃恢复过程分析

    天有不测风云,数据库有旦夕祸福. 前面写 Redo 日志的文章介绍过,数据库正常运行时,Redo 日志就是个累赘. 现在,终于到了 Redo 日志扬眉吐气,大显身手的时候了. 本文我们一起来看看,My ...

  7. vc mysql init 崩溃_故障分析 | 崩溃恢复巨慢原因分析

    作者:xuty 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源. 一.现象 有个 MySQL 5.7 开发库异常挂掉后,奔溃恢复一直处于如下位置,且持 ...

  8. no such file or directory什么意思_为什么这次 MySQL 崩溃恢复要这么久-爱可生

    作者:xuty 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源. 一.现象 有个 MySQL 5.7 开发库异常挂掉后,崩溃恢复一直处于如下位置,且持 ...

  9. mysql数据恢复慢_故障分析 | 崩溃恢复巨慢原因分析

    一.现象 有个 MySQL 5.7 开发库异常挂掉后,奔溃恢复一直处于如下位置,且持续了 2 小时左右才起来.非常疑惑这段时间 MySQL 到底做了什么事情?居然需要这么长时间.虽说这里虚拟机的 IO ...

最新文章

  1. 华为不造车,广汽合作智能驾驶
  2. mysql 挂掉 无法启动_mysql-配置 - MySQL错误,时不时自动挂掉,无法启动
  3. pytorch mseloss bceloss 对比
  4. JAVA中Map集合的使用举例
  5. Xcode7在运行包含HTTP协议的程序时报错解决方法 App Transport Security has blocked a cleartext HTTP (http)...
  6. python打包zip文件_python 解压文件,合并文件 打包成zip格式文件 生成MD5值
  7. Android Lifecycle源码解析(一)
  8. python类库32[多线程同步Lock+RLock+Semaphore+Event]
  9. python pdf转word 表格_太赞了!Pdf转Word,我用Python 轻松搞定表格和水印!
  10. vuecli3 引入全局scss变量_利用scss公共库实现样式和业务组件解耦, 快速提高开发效率!...
  11. NFT抢购合集工具(免费)
  12. c语言scan例子,SCAN和C-SCAN算法图解
  13. MMORPG网络游戏开发之网络通信
  14. 计算机主机内有哪些硬件,电脑主机内部有哪些硬件
  15. 利用npn开关电路,将stm32 IO口输出的0-3.3v的pwm波转换为0-5v的pwm波
  16. mysql一条sql是一个事物么_mysql 事物浅析
  17. Mac 重置 idea
  18. 实验吧决斗场刷新刷新快刷新
  19. fiddler抓APP的htpps請求,全部都是Tunnel to ......CONNECT...443的解决办法
  20. java去掉可最后一个逗号

热门文章

  1. 有限理性建模的方法和计算机平台,有限理性假设下的多方计算协议建模与仿真...
  2. Google Chrome Plus——绿色便携多功能谷歌浏览器
  3. Web前端开发 学习笔记(一)
  4. 致敬生命 看南京鼓楼医院如何打造IT界的“急救中心”
  5. linux命令打开history,Linux的history命令基本使用
  6. 编码:隐匿在计算机背后的语言(1-3章)
  7. 在html语言中超级链接使用什么标签,什么是超链接(详解什么是 HTML 中的超链接标签 a)...
  8. 身为一个男人,我觉得我连狗都不如!
  9. 【luogu CF1693D】Decinc Dividing(DP)
  10. CH55x使用Arduino编程记录(一)