MySQL提升笔记(3)日志文件详解

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL提升笔记(3)日志文件详解

     

在MySQL数据库和InnoDB存储引擎中,有很多种文件,如:参数文件、日志文件、socket文件、pid文件、MySQL表结构文件、存储引擎文件。

本节重点关注日志文件,MySQL的复制、事务等重要功能都和日志文件相关。日志文件主要包括错误日志文件二进制日志文件慢查询日志文件查询日志文件重做日志文件等。其中重做日志文件是InnoDB引擎文件。

1、日志文件介绍

1.1、错误日志(error log)

错误日志文件对MySQL的启动、运行、关闭过程进行了记录,是定位MySQL问题的第一把钥匙。

1.2、慢查询日志(slow query log)

慢查询日志是用来记录执行时间超过 long_query_time 这个变量定义的时长的查询语句。通过慢查询日志,可以查找出哪些查询语句的执行效率很低,以便进行优化。

1.3、一般查询日志(general log)

一般查询日志记录了所有对MySQL数据库请求的信息,无论请求是否正确执行。

默认情况下,general log 是关闭的,开启通用查询日志会增加很多磁盘 I/O, 所以如非出于调试排错目的,不建议开启通用查询日志。

1.4、二进制日志(bin log)

关于二进制日志,它记录了数据库所有执行的DDL和DML语句(除了数据查询语句select、show等),以事件形式记录并保存在二进制文件中。

  • log_bin:指定binlog是否开启及文件名称。
  • server_id:指定服务器唯一ID,开启binlog 必须设置此参数。
  • binlog_format:指定binlog模式,建议设置为ROW。
  • max_binlog_size:控制单个二进制日志大小,当前日志文件大小超过此变量时,执行切换动作。
  • expire_logs_days:控制二进制日志文件保留天数,默认值为0,表示不自动删除,可设置为0~99。

二进制日志文件是非常重要的日志文件,建议开启,二进制日志主要有这么几个作用:

  • 恢复:利用二进制文件恢复数据,原理是取出日志的操作记录,重新执行

image.png

  • 复制:和恢复原理类似,一般分为主库和从库。
  • 审计: 通过观察二进制文件,可以判断是否存在对数据库有危险性的操作。

1.5、重做日志(redo log)

对于InnoDB,重做日志至关重要,因为它们记录了对于InnoDB存储引擎的事务日志。

当实例或介质失败时,如数据库由于所在主机断电导致实例失败,InnoDB存储引擎就会恢复到断电前的时刻,以此来保证数据的完整性。

InnoDB引擎对数据的更新,是先将更新记录写入redo log日志,然后会在系统空闲的时候或者是按照设定的更新策略再将日志中的内容更新到磁盘之中。这就是所谓的预写式技术(Write Ahead logging)。这种技术可以大大减少IO操作的频率,提升数据刷新的效率。

写入重做日志文件也不是直接写,而是先写入一个重做日志缓冲,然后按照一定的条件顺序写入日志文件。

image.png

redo log日志的大小是固定的,为了能够持续不断的对更新记录进行写入,在redo log日志中设置了两个标志位置,checkpoint和write_pos,分别表示记录擦除的位置和记录写入的位置。redo log日志的数据写入示意图可见下图。

image.png

write_pos标志到了日志结尾时,会从结尾跳至日志头部进行重新循环写入。所以redo log的逻辑结构并不是线性的,而是可看作一个圆周运动。write_poscheckpoint中间的空间可用于写入新数据,写入和擦除都是往后推移,循环往复的。

image.png

write_pos追上checkpoint时,表示redo log日志已经写满。这时不能继续执行新的数据库更新语句,需要停下来先删除一些记录,执行checkpoint规则腾出可写空间。

checkpoint规则:checkpoint触发后,将buffer中脏数据页和脏日志页都刷到磁盘。

同样是记录事务日志,和bin log有什么不同呢?

  • bin log会记录所有与数据库有关的日志记录,包括InnoDB、MyISAM等存储引擎的日志,而redo log只记InnoDB存储引擎的日志。
  • 记录的内容不同,bin log记录的是关于一个事务的具体操作内容,即该日志是逻辑日志。而redo log记录的是关于每个页(Page)的更改的物理情况。
  • 写入的时间不同,bin log仅在事务提交前进行提交,也就是只写磁盘一次。而在事务进行的过程中,却不断有redo ertry被写入redo log中。
  • 写入的方式也不相同,redo log是循环写入和擦除,bin log是追加写入,不会覆盖已经写的文件。

image.png

1.6、回滚日志(undo log)

提到了redo log,这里在简单了解一下回滚日志(undo log)。

回滚日志同样也是InnoDB引擎提供的日志,顾名思义,回滚日志的作用就是对数据进行回滚。当事务对数据库进行修改,InnoDB引擎不仅会记录redo  log,还会生成对应的undo log日志;如果事务执行失败或调用了rollback,导致事务需要回滚,就可以利用undo  log中的信息将数据回滚到修改之前的样子。

但是undo log不redo  log不一样,它属于逻辑日志。它对SQL语句执行相关的信息进行记录。当发生回滚时,InnoDB引擎会根据undo  log日志中的记录做与之前相反的工作。比如对于每个数据插入操作(insert),回滚时会执行数据删除操作(delete);对于每个数据删除操作(delete),回滚时会执行数据插入操作(insert);对于每个数据更新操作(update),回滚时会执行一个相反的数据更新操作(update),把数据改回去。undo  log由两个作用,一是提供回滚,二是实现MVCC。

2、更新语句执行

接下来结合一条更新语句的执行,来进一步理解bin log和redo log这两种重要日志。

 update t set c=c+1 where ID=2;

2.1、更新语句执行流程

我们来看执行器和InnoDB引擎在执行这个简单的update语句时的内部流程。

  1. 执行器先找引擎取ID=2这一行。ID是主键,引擎直接用树搜索找到这一行。如果ID=2这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  2. 执行器拿到引擎给的行数据,把这个值加上1,比如原来是N,现在就是N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
  3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态。然后告知执行器执行完成了,随时可以提交事务。
  4. 执行器生成这个操作的binlog,并把binlog写入磁盘。
  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交(commit)状态,更新完成。

update语句的执行流程图如下:

image.png

2.2、两阶段提交

这条语句的执行过程中,redo log的写入分成了两个步骤分成了prepare和commit两个阶段进行提交,这就是所谓的两阶段提交。为什么要用两阶段提交呢?

先用通俗的说法:

比如小明去超市里买一瓶可乐:

  1. 小明:老板给我来瓶可乐!透心凉心飞扬的那个。
  2. 老板:机器扫一下可乐,告诉小明这瓶可乐2块5,给钱(记录 redo log,事务处于prepare状态)
  3. 收钱放入钱箱(记录 binlog,事务实际是否完成的根本依据,处于待标记commit阶段)
  4. 然后让小明把可乐拿走(redo log 状态标为 commit,表示该事务逻辑闭环)。到这里,代表一笔交易结束。
  5. 等算账前再把这一天卖东西的交易信息一起同步到数据库。

可见,如果收钱之前(prepare阶段,步骤3)交易被打断,回过头来处理此次交易,发现只有记了小黑板但没有收钱,则交易失败,删掉小黑板上的记录(回滚);

如果收了钱后(commit阶段 或 待commit阶段,步骤4 || 5)交易被打断,然后回过头发现系统上有记录(prepare)而且钱箱有本次收入(bin log),则说明本次交易有效,补充修改commit状态,更新到库存中。


用正式一点的语言来描述。

如果不用两阶段提交,要么就是先写完redo log再写binlog,或者采用反过来的顺序。我们看看这两种方式会有什么问题。

仍然用前面的update语句来做例子。假设当前ID=2的行,字段c的值是0,再假设执行update语句过程中在写完第一个日志后,第二个日志还没有写完期间发生了crash,会出现什么情况呢?

  1. 先写redo log后写binlog。假设在redo log写完,binlog还没有写完的时候,MySQL进程异常重启。由于我们前面说过的,redo log写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行c的值是1。
    但是由于binlog没写完就crash了,这时候binlog里面就没有记录这个语句。因此,之后备份日志的时候,存起来的binlog里面就没有这条语句。
    然后你会发现,如果需要用这个binlog来恢复临时库的话,由于这个语句的binlog丢失,这个临时库就会少了这一次更新,恢复出来的这一行c的值就是0,与原库的值不同。

image.png

  1. 先写binlog后写redo log。如果在binlog写完之后crash,由于redo   log还没写,崩溃恢复以后这个事务无效,所以这一行c的值是0。但是binlog里面已经记录了“把c从0改成1”这个日志。所以,在之后用binlog来恢复的时候就多了一个事务出来,恢复出来的这一行c的值就是1,与原库的值不同。

image.png

可以看到,如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。

你可能会说,这个概率是不是很低,平时也没有什么动不动就需要恢复临时库的场景呀?

其实不是的,不只是误操作后需要用这个过程来恢复数据。当你需要扩容的时候,也就是需要再多搭建一些备库来增加系统的读能力的时候,现在常见的做法也是用全量备份加上应用binlog来实现的,这个“不一致”就会导致你的线上出现主从数据库不一致的情况。

简单说,redo log和binlog都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。

2.3、日志落盘

保证事务成功,日志必须落盘,这样,数据库crash后,就不会丢失某个事务的数据了

  • innodb_flush_log_at_trx_commit 这个参数设置成 1 的时候,表示每次事务的 redo log 都直接持久化到磁盘。这样可以保证 MySQL 异常重启之后数据不丢失。
  • sync_binlog 这个参数设置成 1 的时候,表示每次事务的 binlog 都持久化到磁盘。这样可以保证 MySQL 异常重启之后 binlog 不丢失。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
27天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
131 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
6天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
27天前
|
SQL Oracle 关系型数据库
【赵渝强老师】Oracle的控制文件与归档日志文件
本文介绍了Oracle数据库中的控制文件和归档日志文件。控制文件记录了数据库的物理结构信息,如数据库名、数据文件和联机日志文件的位置等。为了保护数据库,通常会进行控制文件的多路复用。归档日志文件是联机重做日志文件的副本,用于记录数据库的变更历史。文章还提供了相关SQL语句,帮助查看和设置数据库的日志模式。
【赵渝强老师】Oracle的控制文件与归档日志文件
|
22天前
|
关系型数据库 MySQL 数据库
【赵渝强老师】MySQL的binlog日志文件
MySQL的binlog日志记录了所有对数据库的更改操作(不包括SELECT和SHOW),主要用于主从复制和数据恢复。binlog有三种模式,可通过设置binlog_format参数选择。示例展示了如何启用binlog、设置格式、查看日志文件及记录的信息。
|
27天前
|
Oracle 关系型数据库 数据库
【赵渝强老师】Oracle的参数文件与告警日志文件
本文介绍了Oracle数据库的参数文件和告警日志文件。参数文件分为初始化参数文件(PFile)和服务器端参数文件(SPFile),在数据库启动时读取并分配资源。告警日志文件记录了数据库的重要活动、错误和警告信息,帮助诊断问题。文中还提供了相关视频讲解和示例代码。
|
23天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL的撤销日志文件和错误日志文件
本文介绍了MySQL的物理存储结构,重点讲解了InnoDB存储引擎中的撤销日志文件(undo log)和错误日志文件。从MySQL 8.0开始,默认生成两个10MB的undo表空间文件,并支持动态扩容和收缩。错误日志文件记录了MySQL启动、运行、关闭过程中的问题,通过示例展示了如何查看和使用这些日志。
|
1月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
212 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
271 3
|
2月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1673 14
|
2月前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
39 0