在上一篇中我们提到了MySQL的事务特性,这一片主要讲述事务的实现。

事务的隔离性由锁来实现。原子性,一致性,持久性通过数据库的redo和undo log来实现。

redo恢复提交事务修改页的操作,而undo回滚行记录到某个特定版本。因此两者记录的内容不同,redo通常是物理日志,记录的是页的物理修改操作。undo是逻辑日志,根据每行记录进行记录。

数据库为了保证提交数据的持久性,做了很多努力;回想一下double write,首先把缓冲池中的脏页使用double write技术刷新到磁盘上;想象一种情况,在一个事务的过程中,数据库down掉了,然后数据库恢复的时候会发生什么?因为最后一条事务既没有提交也没有回滚,这时候数据库状态违反了事务的原子性,因此在进行crash recover的时候,需要判断事务是需要提交呢,还是回滚?因此我们引入了redo日志和undo日志。【感觉说的不太准确】

redo日志

重做日志由两部分组成;一是内存中的重做日志缓冲(redo_log buffer);二是重做日志文件,日志文件是持久的!

在事务进行提交时,必须首先将该事务的所有日志写入重做日志文件进行持久化,然后进行comit操作。在INNODB存储引擎中,事务日志由两部分组成redo log和undo log。redo log用来保证事务的持久性,undo log用来帮助事务回滚以及MVCC功能。

redo log基本上是顺序写的,在数据库运行时不需要对redo log进行读取操作,而undo log是需要进行随机读取的。

为了确保每次日志都写入重做日志文件,在每次讲重做日志缓冲写入重做日志文件后,INNODB存储引擎都会调用一次fsync操作。【在刷新的时候虽然开启了O_DIRECT选项,但是文件的元信息并不会改变,因此需要调用fsync函数】因此重做日志缓冲先写入文件系统缓存,为了确保重做日志写入磁盘,必须进行一次fsync操作。由于fsync操作的效率取决于磁盘的性能,因此磁盘的性能决定了事务提交的性能,也就是数据库的性能。

innodb_flush_log_at_trx_commit用来控制重做日志刷新到磁盘的策略。

innodb_flush_log_at_trx_commit:

取值如下:

1: 表示事务提交时必须调用一次fsync操作。

0: 表示事务提交时不进行写入重做日志操作,这个操作仅在master thread中完成,而master thread会每1秒进行一次fsync操作。

2:表示事务提交时将重做日志写入重做日志文件,但仅写入文件系统的缓存,不进行fsync操作,在这个设置下数据库宕机并不会导致事务丢失,但是服务器宕机会导致事务丢失

二进制日志和重做日志

在MySQL数据库中还有一种二进制日志,其用来进行PIT恢复以及主从复制环境的建立。

重做日志是从INNODB存储引擎层产生的,而二进制日志是MySQL数据库的上层产生的。【因为MySQL有不同的存储引擎,为了保证各个引擎的兼容(复制的时候),因此有了二进制日志】。

二进制日志是一种逻辑日志,其记录的是对应的SQL语句,而INNODB存储引擎的重做日志是物理格式,其记录的是对于每个行的修改。

还有就是写入的时间点不同,二进制日志是在事务提交的时候一次性写入的,而重做日志在事务进行中不断的被写入,重做日志并不是随事务的提交顺序进行写入的。

重做日志的内部组成

重做日志都是以512字节的块进行保存的,称之为重做日志块(redo log block)。磁盘的每个扇区的大小也是512字节,因为重做日志的的写入是原子性的,不需要double write。

重做日志块除了日志本身以外,还有日志头和日志尾两部分组成。重做日志头一共占用12字节,重做日志尾占用8字节,因为每个重做日志块实际可以存储大小为492字节,

如图显示了重做日志缓存的结构,可以发现重做日志缓存由每个512字节大小的日志块组成。

log  block header的组成如下:

名称

占用字节

LOG_BLOCK_HDR_NO

4

LOG_BLOCK_HDR_DATA_LEN

2

LOG_BLOCK_FIRST_REC_GROUP

2

LOG_BLOCK_CHECKPOINT_NO

4

log buffer是由log block组成,在内部log buffer就好似一个数组,因此LOG_BLOCK_HDR_NO用来标记这个数组中的位置。其是递增并且循环使用的,占用4个字节,但是由于第一位用来判断是否是flush bit,所以最大的值为2G。(这个应该最大限制应该是MySQL5.5版本的限制,重做日志最大为4G,MySQL5.6之后最大为512G)

LOG_BLOCK_HDR_DATA_LEN: 表示log block所占用的大小。当log block被写满时,该值为0x200.

LOG_BLOCK_FIRST_REC_GROUP:表示第一个日志所在的偏移量。当一个新log block写入数据时,其偏移量为log block的头部大小为12字节。事务t1重做日志为762字节,事务t2的重做日志为100字节,那么需要两个log block,第一个日志日志块的偏移量为12字节,第二个日志块为(762-492+12)=280字节。

LOG_BLOCK_CHECKPOINT_NO:表示该log block最后被写入时的检查点,占用4字节。

日志尾只有一部分组成,其值和LOG_BLOCK_HDR_NO相同。

重做日志的大小管理

在默认的情况下,在INNODB存储引擎的数据目录下面有两个名为ib_logfile0和ib_logfile1的文件。每个INNODB存储引擎至少有1个重做日志文件组,每个文件组下至少有两个文件。为了提高可靠性,用户可以设置多个镜像组,将不同的文件组放在不同的磁盘上,一次提高重做日志的高可用性。在重做日志组中,每个重做日志文件的大小是一样的,并以循环的方式写入数据。

首先写入重做日志文件1,达到文件最后时,会切换到文件2,轮转循环写入数据。

#注意: MySQL5.7中没有镜像这个设置了

mysql> show variables like"innodb_mirrored_log_groups";

Emptyset (0.01sec)

mysql> set innodb_mirrored_log_groups = 2;

ERROR1193 (HY000): Unknown system variable 'innodb_mirrored_log_groups'

重做日志参数设置如下:

innodb_log_file_size: 设定重做日志的大小。(总的大小,在只有1个重做日志组的时候,每个重做日志的大小=innodb_log_file_size/innodb_log_files_in_group)

innodb_log_files_in_group: 每个重做日志组有多少个重做日志文件

innodb_log_group_home_dir: 指定重做日志的位置,默认是在datadir指定的目录下面

innodb_log_buffer_size: log buffer的大小,默认是16

重做日志文件大小设置对于INNODB存储引擎的性能有着非常大的影响。一方面重做日志文件不能设置的太大,如果设置太大,在恢复时可能需要很长时间;另一方面又不能设置的太小,否则可能导致一个事务日志需要多次切换重做日志文件,频繁发生async checkpoin,导致性能抖动。

在INNODB存储引擎中,对于不同的操作有着不同的重做日志格式。虽然各种重做日志的类型不同,但是他们有着基本的格式,如下:

redo_log_type

space

page_no

redo_log_body

redo_log_type: 占用1字节,表示重做日志的类型。

space:表示表空间ID。

page_no:表示页便宜量。

redo_log_body: 表示每个重做日志的数据部分,恢复时需要调用相应的函数进行解析。

undo日志

重做日志记录了事务的行为,可以很好地通过其对页进行“重做”操作。但是事务有时候还要进行回滚操作,这时就需要undo。对数据库进行修改时,INNODB存储引擎不但会产生redo,还会产生一定量的undo。

undo存放在数据库内部一个特殊段中,这个段称为undo段。undo段位于共享表空间内。

undo是逻辑日志,因此只是将数据库逻辑地恢复到原来的样子。所有修改都被逻辑地取消了,但是数据结构和页本身在回滚之后可能大不相同。

除了回滚操作,undo的另一个作用是MVCC,即非锁定一致性读。

undo存储管理:

INNODB存储引擎对undo的管理采用段的方式。在INNODB存储引擎中有rollback segment,每个回滚段记录了1024个undo log segment。而在每个undo log segmetn段中进行undo页的申请。共享表空间偏移量为5的页记录了所有rollback segment header所在的页,这个页类型为FILE_PAGE_TYPE_SYS。

在INNODB1.1版本之前只有一个rollback segment,因此同时支持最大在线事务数为1024.从1.1版本之后最大支持128个rollback segment,其中32个回滚段作为保留用于临时表事务的非重做回滚段,剩余的96个可用的回滚段,每个回滚段支持1023个在线事务的连接。

InnoDB supports 128 rollback segments, 32 of which are reserved as non-redo rollback segments for temporary table transactions. Each transaction

that updates a temporary table (excluding read-only transactions) is assigned two rollback segments, one redo-enabled rollback segment and one

non-redo rollback segment. Read-only transactions are only assigned non-redo rollback segments, as read-only transactions are only permitted to

modify temporarytables.

This leaves96 available rollback segments, each of which supports up to 1023 concurrent data-modifying transactions, for a total limit of

approximately 96K concurrent data-modifying transactions. The 96K limit assumes that transactions do not modify temporary tables. If all

data-modifying transactions also modify temporary tables, the total limit is approximately 32K concurrent data modifying transactions.

For more information about rollback segments that are reserved for temporary table transactions, see Temporary Table Undo Logs.

详见官方文档: https://dev.mysql.com/doc/refman/5.7/en/innodb-undo-logs.html

在INNODB1.1(包含)之前回滚段都存在于共享表空间中,在INNODB1.2之后,可以通过参数对回滚段做进一步的设置。

mysql> show variables like "innodb%undo%";+--------------------------+------------+

| Variable_name | Value |

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

| innodb_max_undo_log_size | 1073741824 | #最大回滚段的大小

| innodb_undo_directory | ./ | #回滚段的文件位置,默认在datadir指定的目录下面

| innodb_undo_log_truncate | OFF | #

| innodb_undo_logs | 128 | #支持的回滚段大小,默认是128个

| innodb_undo_tablespaces | 0 | #构成回滚段文件的数量,若设置,则文件名以undo开头

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

5 rows in set (0)

innodb_undo_log_truncate:回收undo表空间,要求MySQL数据库至少有两个undo表空间,一个保持活跃的状态,另一个处于被回收的状态。

超过innodb_max_undo_log_size定义大小的表空间将会被回收。MySQL5.7才加入的!

mysql> show global variables like '%truncate%';

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

| Variable_name                        | Value |

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

| innodb_purge_rseg_truncate_frequency | 128   |

| innodb_undo_log_truncate             | OFF   |

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

2 rows in set (0.01 sec)

undo的truncate主要由下面两个参数控制:innodb_purge_rseg_truncate_frequency,innodb_undo_log_truncate。1. innodb_undo_log_truncate是开关参数。2. innodb_purge_rseg_truncate_frequency默认128,表示purge undo轮询128次后,进行一次undo的truncate。

当设置innodb_undo_log_truncate=ON的时候, undo表空间的文件大小,如果超过了innodb_max_undo_log_size, 就会被truncate到初始大小,但有一个前提,就是表空间中的undo不再被使用。

其主要步骤如下:1. 超过大小了之后,会被mark truncation,一次会选择一个2. 选择的undo不能再分配新给新的事务3. purge线程清理不再需要的rollback segment4. 等所有的回滚段都释放了后,truncate操作,使其成为install db时的初始状态。

默认情况下, 是purge触发128次之后,进行一次rollback segment的free操作,然后如果全部free就进行一个truncate。

但mark的操作需要几个依赖条件需要满足:1. 系统至少得有两个undo表空间,防止一个offline后,至少另外一个还能工作2. 除了ibdata里的segment,还至少有两个segment可用3. undo表空间的大小确实超过了设置的阈值

MySQL5.7--truncate说明

事务在undo log segment分配页并写入undo log的这个过程同样需要写入重做日志。也就是undo会产生redo log。

当事务提交时,INNODB存储引擎会做以下两件事:

将undo放入到列表中,供之后的purge操作。

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

事务提交后并不马上删除undo log及undo log所在的页。这是因为可能还有其他事务需要通过undo log来得到行记录之前的版本。故事务将undo log放入一个链表中,是否可以删除undo log以及undo log所在的页由purge线程决定。

事务提交时,将undo页放入链表中,然后判断给undo页的使用空间是否小于3/4,若是则表明该undo页可以重用,之后,新的undo log记录在当前undo log的后面。由于存放undo log的列表都是以记录进行组织的,而undo页可能存放着不同事务的undo log,因此purge线程操作需要涉及磁盘的离散读取操作,是一个比较缓慢的过程。

TRANSACTIONS------------

Trx id counter 12041Purge donefor trx's n:o < 0 undo n:o < 0state: running but idle

History list length0 #undo 页的大小LISTOF TRANSACTIONS FOREACH SESSION:---TRANSACTION 421780424370000, not started

0 lock struct(s),

mysql里hdr是什么的缩写_MySQL事务之-2相关推荐

  1. mysql里hdr是什么的缩写_视频hdr什么意思

    大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答. 视频HDR是英文High Dynamic Range(高动态范围)的缩写.这是一种后期处理技术.其特点是可让立体场景更加逼真,大幅 ...

  2. mysql里hdr是什么的缩写_4kHDR是什么意思(4K HDR到底是什么鬼?)

    随着电视行业飞快的发展,各种成像技术和制作工艺都满含黑科技.甚至乎刚刚才了解完一种电视的新技术,然后隔天又有更新的技术运用在电视上面了.还记得以前电视的迭代一般都5-7年甚至更久,而现在处于一个属于科 ...

  3. mysql里hdr是什么的缩写_使用innodb_ruby分析InnoDb索引文件

    innodb_ruby工具的安装 前置条件: 安装ruby和gem mysql的版本5.7(mysql8可能不支持) #检查ruby和gem gem -v ruby -v 安装命令 gem insta ...

  4. mysql里hdr是什么的缩写_hdr是什么意思 hdr功能是什么?

    目前不少朋友选购的一些较为高端的手机均支持HDR功能,很多手机爱好者朋友对于HDR是什么意思以及支持HDR技术手机有什么用不是很了解,甚至不少朋友都没有听说过HDR这一次词,下面本文为大家普及下HDR ...

  5. mysql里hdr是什么的缩写_HDR 是什么?有哪些具体介绍?

    原标题:HDR 是什么?有哪些具体介绍? HDR,高光动态渲染,概念我就不多做解释了. 为什么要HDR? 我们一般的显示器只能显示8位色,就是灰度从黑(0)到白(255)共有_256_个等级. 但是, ...

  6. MySQL里和trunc函数相同的_mysql 函数中与Oracle中ltrim函数功能相同的函数是什么函数?...

    一.ANSI字符函数 字符函数用于在SQL里以不同于存储方式的格式来表示字符串. 串接就是把两个单独的字符串组合为一个. 子串的概念就是从字符串里提取一部分. TRANSLATE函数用于逐字符地把一个 ...

  7. mysql里条件语句和循环语句_MySQL与Oracle 差异比较之四条件循环语句

    循环语句 编号 类别 oracle Mysql 注释 1 IF语句使用不同 IFiv_weekly_day = 'MON'THEN ii_weekly_day := 'MON'; ELSIFiv_we ...

  8. mysql里的char怎么添加数据类型_MySQL CHAR 数据类型

    MySQL CHAR 数据类型 简介:在本教程中,您将了解MySQL CHAR数据类型以及如何在数据库表设计中应用它. MySQL CHAR数据类型简介 CHAR数据类型是MySQL中的固定长度的字符 ...

  9. mysql view 能和表关联吗_MySQL 事务隔离及实现,赶快码上收藏!满满干货

    前言 写文不易,欢迎大家一起交流,喜欢文章记得关注我点个赞哟,感谢支持!(文末还有福利与彩蛋哦!) 1. 事务的 ACID 特性 Actomic,原子性:一个事务中的所有操作,要么全部完成,要么全部失 ...

最新文章

  1. 136 - Ugly Numbers
  2. hadoop 实现序列化
  3. 远程连接 Mysql 失败的解决方法
  4. random是python的内置函数吗_Python 内置函数math,random
  5. vue-项目完成的项目报告
  6. SMA、SPI、LTE
  7. codevs 4093 EZ的间谍网络
  8. blos硬盘启动台式计算机,bios设置硬盘启动,最全的bios设置硬盘启动详细方法(两种模式)...
  9. 炒伦敦金哪个平台正规?2021香港排名前10伦敦金交易平台一览
  10. Cesium基础知识-创建3D地球
  11. android adb 模拟长按,adb 模拟长按电源键
  12. volatile的区别
  13. 认识常见壳与程序的特征
  14. 什么是 web API? DOM和BOM
  15. CI/CD流水线技术方案
  16. vue系列教程之微商城项目|主页
  17. Android中的缓存策略,实战打造ImageLoader
  18. 如何区分Workflow、BPM与PRA?三者之间有什么关系?
  19. 百家号视频怎么消重批量处理去重消重去水印去logo软件视频MD5修改工具(短视频去重) 自媒体如何解...
  20. 一起来学k8s 38. 二进制k8s集群安装EFK

热门文章

  1. 减少cookie传输_如何使用Cookie减少WordPress垃圾评论
  2. java 父类转换成子类的方法
  3. ZYNQFPGA 串口通信原理
  4. 让你终身受益的5个定律
  5. detectron2的简介和配置
  6. 论文写作课的收获与体会
  7. 很多人还不知道中视频计划手机上发布多端横竖屏视频的方法
  8. Java毕设项目——人才招聘网站(java+SpringBoot+Maven+Mysql+Jsp)
  9. 【聯強EMBA】「本能叛逆」與「理性叛逆」
  10. vue、ECharts、flexible.js在移动端的自适应安卓、苹果等机型的分辨率