百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

MySql中必须知道的至关重要的三种日志

nanshan 2025-03-06 17:50 10 浏览 0 评论

前言:

MySql 中有三种 「log」 是十分中要的,因为MySql之所以能支持 事务(实现持久化、回滚等)、数据库崩溃恢复、主从复制等,都是基于这三种日志的。

至关重要的三种log:

  • binlog 二进制日志
  • redo log 重做日志
  • undo log 回滚日志

本文主线:

  • 简要介绍三种日志
  • MySql事务处理中三种日志承担的角色

简要介绍三种日志:

1、binlog 二进制日志:

binlog 二进制日志(归档日志),这个日志是由MySql的 server层 进行维护的;不管当前MySql使用的是什么存储引擎,binlog归档日志都是支持的;

对MySql的server层不清楚的大大们可以参考此文章:查询SQL的执行流程

「作用:」

  • 用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。
  • 数据恢复,用于数据库的基于时间点的还原。

「内容:」

逻辑格式的日志,binlog是用于记录所有数据库表结构和表数据变更的二进制日志,比如insert、update、delete、create、truncate等等操作,不会记录select、show操作,因为它们没有对数据本身发生改变。

「常见格式:」

MySql的binlog的默认格式是使用 STATEMENT;需要记住的是使用此格式时,如果将事务隔离级别设置为 RC都已提交 时,在进行主从复制的时候会存在bug,导致复制后主从数据不一致;

具体存在什么样的bug可以参考此文章:互联网项目中mysql应该选什么事务隔离级别

「注意:」

binlog二进制日志文件在默认情况下并没有启动,需要手动进行开启的;有人可能会质疑,开启此日志文件的话,对数据库的性能会产生什么样的影响?

质疑是对的,确实开启此日志文件会影响到数据库的性能,但是这个影响是十分有限的,根据MySql的官网手册了解到,开启此日志会使性能下降1%左右,这个损失大体上是可以接受的。

2、redo log 重做日志:

redo log重做日志,这个日志是由MySql的 innodb存储引擎 提供维护的,此日志文件只存在于innodb存储引擎下;

「作用:」

确保事务的 持久性 。redo日志记录事务执行后的状态,用来恢复未写入data file的已成功事务更新的数据。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。

各位大大,如果上面这段话如果看得不是很明白,可以继续往下看看呀,通过下文中事务的例子可以很好理解;

「内容:」

物理格式的日志,记录的是物理数据页面的修改的信息,简单说就是记录着xxx页做了xxx修改;

innodb 存储引擎提供了重做日志文件组(group),每个重做日志文件组包含着重做日志文件;默认是提供了一个重做日志文件组,文件组下包含两个大小相同的重做日志文件;

innodb存储引擎的重做日志文件写入流程:先写重做日志文件1,当文件1被顺序写满时,会切换到重做日志文件2,再当重做日志文件2也被写满时,会再切换到重做日志文件1中,依次循环; 所以说重做日志文件是 循环覆盖写入的

因为重做日志是循环覆盖写入的,所以不能使用其进行整个数据库的数据恢复,它只能保证数据库宕机时的事务的完整性数据;如果想要恢复全部数据的话,只能使用 binlog 二进制日志(归档日志)进行恢复。

注意:大家可以手动修改重做日志文件组下的文件数量,并可以指定每个重做日志文件的大小,通过下面的参数:

  • innodb_log_file_size 指定重做日志文件的大小
  • innodb_log_files_in_group 重做日志文件组下的文件数量

「扩展:」

注意:重做日志文件的大小设置对于innodb存储引擎的性能有很大的影响。

重做日志文件不能设置的太大,也不能设置的太小;如果设置的太大,在数据库意外宕机后进行恢复时会需要很长时间;

但是也不能设置的太小,因为设置的太小会导致一个事务的日志需要多次切换重做日志文件进行写入,那么在覆盖掉之前的重做日志时,需要将要被覆盖的重做日志对应在内存中的脏页进行写盘(刷盘);

因为不写盘的话,如果重做日志被覆盖掉了,然后数据库意外宕机了,那么之前没有写盘的数据将没法在数据库重启时进行恢复了,并且如果频繁的进行重做日志的覆盖的话,那么就会频繁的进行脏页刷盘,进而导致数据库性能的抖动。

那重做日志应该设置多大呢? 一般来说,redo log日志文件的全部大小,应该足够容纳服务器一个小时的活动内容。

如果统计出一小时的重做日志写入量为 500M 的话,由于 redo log 日志文件默认有 2 个,所以需要设置 innodb_log_file_size=250M ;

注意:如果各位大大们对 脏页等名词 不太清楚的话,可以通过《神奇大佬 - MySQL实战45讲》、《mysql技术内幕 innodb存储引擎》进行学习了解呀。

3、undo log 回滚日志:

注意 undo log 回滚日志的写入是在事务开始执行前就已经开始了;

「作用:」

保证数据的原子性,保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读;

「内容:」

逻辑格式的日志,在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于redo log的。

比如说我们要insert一条数据,那么undo log就会生成一条对应的delete日志,并且与当前事务的txid(事务唯一标识)进行了关联,用于支持回滚和MVCC;

像如果在一个事务中执行了多个包含update、insert、delete的语句时,由于事务具备原子性,如果其中一个语句执行失败,那么之前执行成功的语句要就要被回滚撤销掉,此时就会根据当前事务txid在undo log中查找到保存的日志进行执行回滚;

注意:写入undo log 的这个操作也是需要记录到redo log重做日志中的;

为什么也要记录到redo log中呢? 举个场景,当事务在没执行完时mysql意外宕机了,那么在数据库重启后需要恢复事务,如果事务需要回滚,但是你在内存中保存的undo log还没有写入磁盘,在宕机时就丢失了,那么就会导致无法回滚,就会出现数据不一致的问题;而如果记录到了redo log中,则可以根据redo log进行重做,然后根据重做的undo log进行回滚。

「扩展:」

注意:为了提升数据库性能,mysql都是在内存的缓冲区中记录日志,然后根据策略再进行刷盘的(将缓冲区记录的日志写入到磁盘中进行保存);

通过innodb存储引擎的架构图可以进行深入了解:

如果想深入学习,请参考此文章 你居然还不知道Mysql存储引擎InnoDB分为内存架构、磁盘架构?

MySql事务处理中三种日志承担的角色:

首先咱通过一个update语句的执行流程图展示出三种日志文件在事务处理中承担的角色! SQL语句如下:

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

为什么流程图中没有undo log:

在流程图中可以看到redo log、binglog,那怎么没有undo log 呀,因为 undo log在 事务开始执行前 就已经开始写入了 。

为什么上图事务中必须存在redo log 和 binlog呢:

首先,上面介绍这两种日志时,已经说道了binlog 是mysql的server层维护的日志,主要用来做主从复制和数据备份恢复使用;而redo log是InnoDB存储引擎独有的日志,是用来实现crash-safe能力;

「crash-safe 是什么?」

即在 InnoDB 存储引擎中,事务提交过程中任何阶段,MySQL突然崩溃,重启后都能保证事务的完整性,已提交的数据不会丢失,未提交完整的数据会自动进行回滚。

为了实现crash-safe除了需要redo log外,还需要 undo log对未完整的事务进行回滚的;

想要对crash-safe进行详细了解的大大们可以参考此文章:MySQL 的 crash-safe 原理解析

上图中处于prepare阶段、处于commit阶段是什么:

其实这是mysql的内部XA事务!俗称日志的两阶段提交协议!看到这大家是不是有点模糊了,听说过分布式XA事务,怎么还有内部XA事务呀?

其实大家知道的分布式XA事务指的是mysql的外部XA事务;内部xa事务主要是mysql内部为了保证binlog与redo log之间数据的一致性而存在的,这也是由其架构决定的(binlog由mysql的server层提供支持,而redo log 则是由 innodb存储引擎层提供支持);

对mysql的架构不太熟悉的大大可以参考此文章:查询SQL的执行流程

binlog与redo log之间数据的一致性问题是什么:

因为redo log 和 binlog 都是用来"恢复" 数据的,redo log是用来恢复事务,保证事务的完整性的,而 binlog 是可以用来进行整体数据恢复,或基于某个时间点进行恢复的,并且用于主从复制;

如果在进行一个事务执行时,已经完成了 redo log重做日志的写入,但是还没有写入binlog,此时数据库意外宕机了,如果没有保障两个日志 逻辑上一致 的话;

那么在数据库重启时会根据redo log进行事务恢复,并将在事务中已经处理好但未写盘的数据进行恢复;但是由于binlog没有写入,所以会导致在使用binlog进行数据恢复时,或者是主从复制时,出现数据不一致的情况;

如果保证了两个日志的逻辑一致的话,那么在使用redo log恢复事务时,会判断binlog是否也写入成功了,如果binlog也写入成功,那么才会进行事务恢复,否则将不进行事务恢复,会使用undo log 进行回滚的;

MySql内部XA事务是什么呢:

内部XA事务就是将事务提交分为了两个阶段,prepare阶段和commit阶段!

prepare:写入redo log,并将回滚段置为prepared状态,此时binlog不做操作。

commit:innodb释放锁,释放回滚段,设置提交状态,写入binlog,然后存储引擎层提交。

扩展:

各位大大们,上图update的语句执行流程中,写入redo log重做日志,写入binglog二进制日志,其实都只是 写入到日志缓冲区中,后面还会涉及到日志缓冲区中数据写入到具体磁盘中的日志文件中;

那何时才会将缓冲区的日志数据写入到磁盘中?这是由mysql中的几个配置参数控制的;

「缓冲区的日志写入到磁盘中的流程:」

在介绍配置参数前,咱们先了解下缓冲区的日志写入到磁盘中的流程是什么样:

  • 用户空间:是指用户程序运行的空间,例如mysql就运行在此空间内;
  • 内核空间: 内核空间是指操作系统内核运行的空间,是为了保证操作系统内核的能够安全稳定地运行而为内核专门开辟的空间;

为什么需要内核空间呢?

主要是为了安全起见,不能让用户空间的程序直接去磁盘空间中读取数据,必须由经由内核空间通过DMA来获取;并且用户空间和内核空间两者之间是互相隔离的 。

「redo log刷盘配置参数:」

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

该参数的值存在三种:

  • 0:表示事务提交时不进行写入重做日志的操作,MySql会使用其后台线程每一秒将日志缓冲区中的重做日志写入到 OS cache(磁盘缓存),同时立即调用 fsync 操作将 OS cache 中的重做日志写入到磁盘文件中(刷盘);
  • 1:表示在事务提交时就会进行重做日志的写入操作,实时的将日志缓冲区中的重做日志写入到 OS cache(磁盘缓存),同时立即调用 fsync 操作将 OS cache 中的重做日志写入到磁盘文件中(刷盘); 此值为默认值 ,因为当设置值为1时可以保证事务的ACID中的持久性;
  • 2:表示在事务提交时就会进行重做日志的写入操作,但是只是将日志缓冲区中的重做日志写入到 OS cache(磁盘缓存),不会立即调用 fsync 操作进行刷盘,MySQL后面会主动将OS cache中的重做日志数据每秒批量进行一次刷盘; 选择此值时,mysql的并发性最好,但是存在风险,当操作系统一旦宕机,会丢数据,但是如果MySql数据库宕机的话,则不会丢失数据,因为数据保存在了OS cache中;

「binlog 刷盘配置参数:」

sync_binlog 配置参数用来控制二进制日志刷新到磁盘的策略。

该参数常用的三种值:

  • 0:表示在事务提交后,mysql会将日志缓冲区中的binlog数据写入到 OS cache(磁盘缓存),但并不会调用 fsync 操作进行刷盘,而是由操作系统自己控制它的缓存的刷盘; 此值为默认值
  • 1:表示在事务提交时就会进行binlog的写入操作,实时的将日志缓冲区中的重做日志写入到 OS cache(磁盘缓存),同时立即调用 fsync 操作将 OS cache 中的重做日志写入到磁盘文件中(刷盘);
  • N:表示每次进行提交后都只是将日志缓冲区中的binlog数据写入到 OS cache(磁盘缓存),在进行N次事务提交以后,Mysql将执行一次fsync操作指令将OS cache中的binlog数据批量刷新到磁盘中; 注意 N 代表的是数值;

「一道经典的面试题:」

面试官:你有遇到过数据库宕机重启,事务丢失的情况么?

我们:其实这道题就是redo log、binlog的刷盘时机,上面已经聊了这两种日志的全部刷盘时机了,大家可以两两结合进行回答就好了;

也可以直接参考此文中提供的答案进行回答:面试官:谈谈你对mysql事务的认识?

各位大大们,MySql中至关重要的三种日志就介绍到此啦;由于本人水平有限,如有问题请留言讨论呀!

点赞 + 评论 + 转发 哟

如果本文对您有帮助的话,请挥动下您爱发财的小手点下赞呀,您的支持就是我不断创作的动力,谢谢啦!

相关推荐

使用nginx配置域名及禁止直接通过IP访问网站

前段时间刚搭建好这个网站,一直没有关注一个问题,那就是IP地址也可以访问我的网站,今天就专门研究了一下nginx配置问题,争取把这个问题研究透彻。1.nginx配置域名及禁止直接通过IP访问先来看n...

如何在 Linux 中使用 PID 号查找进程名称?

在Linux的复杂世界中,进程是系统运行的核心,每个进程都由一个唯一的「进程ID」(PID)标识。无论是系统管理员在排查失控进程,还是开发者在调试应用程序,知道如何将PID映射到对应的进程名称都是一项...

Linux服务器硬件信息查询与日常运维命令总结

1.服务器硬件信息查询1.1CPU信息查询命令功能描述示例lscpu显示CPU架构、核心数、线程数等lscpucat/proc/cpuinfo详细CPU信息(型号、缓存、频率)cat/proc/c...

Ubuntu 操作系统常用命令详解(ubuntu常用的50个命令)

UbuntuLinux是一款流行的开源操作系统,广泛应用于服务器、开发、学习等场景。命令行是Ubuntu的灵魂,也是高效、稳定管理系统的利器。本文按照各大常用领域,详细总结Ubuntu必学...

从 0 到 1:打造基于 Linux 的私有 API 网关平台

在当今微服务架构盛行的时代,API网关作为服务入口和安全屏障,其重要性日益凸显。你是否想过,不依赖商业方案,完全基于开源组件,在Linux上构建一个属于自己的私有API网关平台?今天就带你...

Nginx搭建简单直播服务器(nginx 直播服务器搭建)

前言使用Nginx+Nginx-rtmp-module在Ubuntu中搭建简单的rtmp推流直播服务器。服务器环境Ubuntu16.04相关概念RTMP:RTMP协议是RealTi...

Linux连不上网?远程卡?这篇网络管理指南你不能错过!

大家好!今天咱们聊个所有Linux用户都躲不开的“老大难”——网络管理。我猜你肯定遇到过这些崩溃时刻:新装的Linux系统连不上Wi-Fi,急得直拍桌子;远程服务器SSH连不上,提示“Connecti...

7天从0到上线!手把手教你用Python Flask打造爆款Web服务

一、为什么全网开发者都在疯学Flask?在当今Web开发的战场,Flask就像一把“瑞士军刀”——轻量级架构让新手3天速成,灵活扩展能力又能支撑百万级用户项目!对比Django的“重型装甲”,Flas...

nginx配置文件详解(nginx反向代理配置详解)

Nginx是一个强大的免费开源的HTTP服务器和反向代理服务器。在Web开发项目中,nginx常用作为静态文件服务器处理静态文件,并负责将动态请求转发至应用服务器(如Django,Flask,et...

30 分钟搞定 Docker 安装与 Nginx 部署,轻松搭建高效 Web 服务

在云计算时代,利用容器技术快速部署应用已成为开发者必备技能。本文将手把手教你在阿里云轻量应用服务器上,通过Docker高效部署Nginx并发布静态网站,全程可视化操作,新手也能轻松上手!一、准...

Nginx 配置实战:从摸鱼到部署,手把手教你搞定生产级配置

各位摸鱼搭子们!今天咱不聊代码里的NullPointerException,改聊点「摸鱼必备生存技能」——Nginx配置!先灵魂拷问一下:写了一堆接口却不会部署?服务器被恶意请求打崩过?静态资源加载...

如何使用 Daphne + Nginx + supervisor部署 Django

前言:从Django3.0开始支持ASGI应用程序运行,使Django完全具有异步功能。Django目前已经更新到5.0,对异步支持也越来越好。但是,异步功能将仅对在ASGI下运行的应用程序可用...

Docker命令最全详解(39个最常用命令)

Docker是云原生的核心,也是大厂的必备技能,下面我就全面来详解Docker核心命令@mikechen本文作者:陈睿|mikechen文章来源:mikechen.cc一、Docker基本命令doc...

ubuntu中如何查看是否已经安装了nginx

在Ubuntu系统中,可以通过以下几种方法检查是否已安装Nginx:方法1:使用dpkg命令(适用于Debian/Ubuntu)bashdpkg-l|grepnginx输出...

OVN 概念与实践(德育概念的泛化在理论和实践中有什么弊端?)

今天我们来讲解OVN的概念和基础实践,要理解本篇博客的内容,需要前置学习:Linux网络设备-Bridge&VethPairLinux网络设备-Bridge详解OVS+Fa...

取消回复欢迎 发表评论: