第14章 MySQL事务日志【3.事务篇】【MySQL高级】3

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 第14章 MySQL事务日志【3.事务篇】【MySQL高级】3

innodb_flush_log_at_trx_commit=0


小结: innodb_flush_log_at_trx_commit=o


为0时,master thread中每1秒进行一次重做日志的fsync操作,因此实例crash最多丢失1秒钟内的事务。( master thread是负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性)


数值0话,是一种折中的做法,它的IO效率理论是高于1的,低于2的,这种策略也有丢失数据的风险,也无法保证D。

2.举例

比较innodb_flush_log_at_trx_commit对事务的影响。

#10-事务日志
USE atguigudb3;
CREATE TABLE test_load(
a INT,
b CHAR(80)
)ENGINE=INNODB;
#创建存储过程,用于向test_load中添加数据
DELIMITER//
CREATE PROCEDURE p_load(COUNT INT UNSIGNED)
BEGIN
DECLARE s INT UNSIGNED DEFAULT 1;
DECLARE c CHAR(80)DEFAULT REPEAT('a',80);
WHILE s<=COUNT DO
INSERT INTO test_load SELECT NULL,c;
COMMIT;
SET s=s+1;
END WHILE;
END //
DELIMITER;
#测试1:
#设置并查看:innodb_flush_log_at_trx_commit
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
#set GLOBAL innodb_flush_log_at_trx_commit = 1;
#调用存储过程
CALL p_load(30000); #1min 28sec
#测试2:
TRUNCATE TABLE test_load;
SELECT COUNT(*) FROM test_load;
SET GLOBAL innodb_flush_log_at_trx_commit = 0;
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
#调用存储过程
CALL p_load(30000); #37.945 sec
#测试3:
TRUNCATE TABLE test_load;
SELECT COUNT(*) FROM test_load;
SET GLOBAL innodb_flush_log_at_trx_commit = 2;
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
#调用存储过程
CALL p_load(30000); #45.173 sec

下表显示了在innodb_flush_log_at_trx_commit的不同设置下,调用存储过程p_load插入3万行记录所需的时间:


而针对上述存储过程,为了提高事务的提交性能,应该在将3万行记录插入表后进行一次的COMMIT操作,而不是每插入一条记录后进行一次COMMIT操作。这样做的好处是可以使事务方法在rollback时回滚到事务最开始的确定状态。


虽然用户可以通过设置参数innodb_flush_log_at_trx_commit为0或2来提高事务提交的性能,但需清楚,这种设置方法丧失了事务的ACID特性。

1.7 写入redo log buffer 过程

1.补充概念:Mini-Transaction

MySQL把对底层页面中的一次原子访问的过程称之为一个Mini-Transaction,简称mtr,比如,向某个索引对应的B+树中插入一条记录的过程就是一个Mini-Transaction。一个所谓的mtr可以包含一组redo日志,在进行崩溃恢复时这一组redo日志作为一个不可分割的整体。


一个事务可以包含若干条语句,每一条语句其实是由若干个mtr组成,每一个mtr又可以包含若干条redo日志,画个图表示它们的关系就是这样:



2. redo 日志写入log buffer

向log buffer中写入redo日志的过程是顺序的,也就是先往前边的block中写,当该block的空闲空间用完之后再往下一个block中写。当想往log buffer中写入redo日志时,第一个遇到的问题就是应该写在哪个block的哪个偏移量处,所以InnoDB的设计者特意提供了一个称之为buf_free的全局变量,该变量指明后续写入的redo日志应该写入到 log buffer中的哪个位置,如图所示:


一个mtr执行过程中可能产生若干条redo日志,这些redo日志是一个不可分割的组,所以其实并不是每生成一条redo日志,就将其插入到log buffer中,而是每个mtr运行过程中产生的日志先暂时存到一个地方,当该mtr结束的时候,将过程中产生的一组redo日志再全部复制到log bulffer中。假设有两个名为T1、T2的事务,每个事务都包含2个mtr,我们给这几个mtr命名一下;


事务T1的两个mtr分别称为mtr_T1_1和mtr_T1_2

事务T2的两个mtr分别称为mtr_T2_1和mtr_T2_2

每个mtr都会产生一组redo日志,用示意图来描述一下这些mtr产生的日志情况:


不同的事务可能是并发执行的,所以T1、T2之间的mtr可能是交替执行的。每当一个mtr执行完成时,伴随该mtr生成的一组redo日志就需要被复制到log buffer中,也就是说不同事务的mtr可能是交替写入log buffer的,我们画个示意图(为了美观,把一个mtr中产生的所有的redo日志当作一个整体来画):


有的mtr产生的redo日志量非常大,比如1mtr_t1_2产生的redo日志占用空间比较大,占用了3个block来存储。

3. redo log block的结构图

一个redo log block是由日志头日志体日志尾组成。日志头占用12字节,日志尾占用8字节,所以一个block真正能存储的数据就是512-12-8=492字节。
为什么一个block设计成512字节?

这个和磁盘的扇区有关,机械磁盘默认的扇区就是512字节,如果要写入的数据大于512字节,那么要写入的扇区肯定不止一个,这时就要涉及到盘片的转动,找到下一个扇区,假设现在需要写入两个扇区A和B,如果扇区A写入成功,而扇区B写入失败,那么就会出现非原子性的写入,而如果每次只写入和扇区的大小一样的512字节,那么每次的写入都是原子性的


真正的redo日志都是存储到占用496字节大小的log block body中,图中的log block headerlog block trailer存储的是一些管理信息。我们来看看这些所谓的管理信息都有什么




log block header的属性分别如下:


LOG_BLOCK_HDR_NO : log buffer是由log block组成,在内部log buffer就好似一个数组,因此LOG_BLOCK_HDR_NO用来标记这个数组中的位置。其是递增并且循环使用的,占用4个字节,但是由于第—位用来判新是否是flush bit,所以最大的值为2G。

LOG_BLOCK_HDR_DATA_LEN∶表示block中已经使用了多少字节,初始值为12(因为log block body从第12个字节处开始)。随着往block中写入的redo日志越来也多,本属性值也跟着增长。如果log block body已经被全部写满,那么本属性的值被设置为512

LOG_BLOCK_FIRST_REC_GROUP :一条redo日志也可以称之为一条redo日志记录(redo log record),一个mtr会生产多条redo日志记录,这些redo日志记录被称之为一个redo日志记录组(redo log record group)。LOG_BLOCK_FIRST_REC_GROUP就代表该block中第一个mtr生成的redo日志记录组的偏移量(其实也就是这个block里第一个mtr生成的第一条redo日志的偏移量)。如果该值的大小

LOG_BLOCK_HDR_DATA_LEN相同,则表示当前log block不包含新的日志。

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

log block trailer中属性的意思如下:


LOG_BLOCK_CHECKSUN:表示block的校验值,用于正确性校验(其值和LOG_BLOCK_HDR_NO相同),暂时不关心它。

1.8 redo log file

1.相关参数设置




innodb_log_group_home_dir :指定 redo log 文件组所在的路径,默认值为 ./ ,表示在数据库的数据目录下。MySQL的默认数据目录( var/lib/mysql )下默认有两个名为 ib_logfile0 和ib_logfile1 的文件,log buffer中的日志默认情况下就是刷新到这两个磁盘文件中。此redo日志文件位置还可以修改。

mysql> show variables like 'innodb_log_group_home_dir';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_log_group_home_dir | ./    |
+---------------------------+-------+
1 row in set (0.00 sec)
  • innodb_log_files_in_group:指明redo log file的个数,命名方式如:ib_logfile0,iblogfile1…iblogfilen。默认2个,最大100个。
show variables like 'innodb_log_files_in_group';
/*
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_log_files_in_group | 2     |
+---------------------------+-------+
*/
#ib_logfile0
#ib_logfile1

innodb_flush_log_at_trx_commit:控制 redo log 刷新到磁盘的策略,默认为1。

innodb_log_file_size:单个 redo log 文件设置大小,默认值为 48M 。最大值为512G,注意最大值指的是整个redo log 系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size)不能大于最大值512G。

show variables like 'innodb_log_file_size';
/*
+----------------------+----------+
| Variable_name | Value |
+----------------------+----------+
| innodb_log_file_size | 50331648 |
+----------------------+----------+
*/

根据业务修改其大小,以便容纳较大的事务。编辑my.cnf文件并重启数据库生效,如下所示

[root@centos7-mysql-1 mysql]#vim /etc/my.cnf
innodb_log_file_size=200M

在数据库实例更新比较频繁的情况下,可以适当加大 redo log组数和大小。但也不推荐redo log设置过大,在MySQL前溃恢复时会重新执行REDO日志中的记录。

相关文章
|
18天前
|
存储 SQL 关系型数据库
MySQL的事务隔离级别
【10月更文挑战第17天】MySQL的事务隔离级别
94 43
|
1月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1611 14
|
24天前
|
SQL 关系型数据库 MySQL
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
尼恩,一位40岁的资深架构师,通过其丰富的经验和深厚的技術功底,为众多读者提供了宝贵的面试指导和技术分享。在他的读者交流群中,许多小伙伴获得了来自一线互联网企业的面试机会,并成功应对了诸如事务ACID特性实现、MVCC等相关面试题。尼恩特别整理了这些常见面试题的系统化解答,形成了《MVCC 学习圣经:一次穿透MYSQL MVCC》PDF文档,旨在帮助大家在面试中展示出扎实的技术功底,提高面试成功率。此外,他还编写了《尼恩Java面试宝典》等资料,涵盖了大量面试题和答案,帮助读者全面提升技术面试的表现。这些资料不仅内容详实,而且持续更新,是求职者备战技术面试的宝贵资源。
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
|
1月前
|
SQL 存储 关系型数据库
Mysql主从同步 清理二进制日志的技巧
Mysql主从同步 清理二进制日志的技巧
25 1
|
18天前
|
存储 关系型数据库 MySQL
MySQL中的Redo Log、Undo Log和Binlog:深入解析
【10月更文挑战第21天】在数据库管理系统中,日志是保障数据一致性和完整性的关键机制。MySQL作为一种广泛使用的关系型数据库管理系统,提供了多种日志类型来满足不同的需求。本文将详细介绍MySQL中的Redo Log、Undo Log和Binlog,从背景、业务场景、功能、底层实现原理、使用措施等方面进行详细分析,并通过Java代码示例展示如何与这些日志进行交互。
29 0
|
1月前
|
SQL 关系型数据库 MySQL
【MySQL】索引和事务
【MySQL】索引和事务
51 0
|
4天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
88 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
1月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
189 3
|
3月前
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
129 3
|
26天前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
26 0
下一篇
无影云桌面