MySql之日志

Buffer Pool
Buffer Pool (缓冲池)是 InnoDB 存储引擎中非常重要的内存结构,顾名思义,缓冲池其实就是类似 Redis 一样的作用,起到一个缓存的作用,因为我们都知道 MySQL 的数据最终是存储在磁盘中的,如果没有这个 Buffer Pool 那么我们每次的数据库请求都会磁盘中查找,这样必然会存在 IO 操作,这肯定是无法接受的。但是有了 Buffer Pool 就是我们第一次在查询的时候会将查询的结果存到 Buffer Pool 中,这样后面再有请求的时候就会先从缓冲池中去查询,如果没有再去磁盘中查找,然后在放到 Buffer Pool 中,如下图(每次加载16kb大小的数据页到Buffer Pool中的16kb大小的缓存页中)

在这里插入图片描述
按照上面的那幅图,这条 SQL 语句的执行步骤大致是这样子的

innodb 存储引擎会在缓冲池中查找 id=1 的这条数据是否存在
发现不存在,那么就会去磁盘中加载,并将其存放在缓冲池中
该条记录会被加上一个独占锁(总不能你在修改的时候别人也在修改吧,这个机制本篇文章不重点介绍,以后会专门写文章来详细讲解)

undo 日志文件:记录数据被修改前的样子(回滚日志)
mvcc
异常时的回滚,保证事务的原子性
归属于InnoDB存储引擎
逻辑日志
在操作任何数据之前,首先将数据备份到一个地方,这个存储数据备份的地方称之为undo log。然后进行数据的修改,如果出现了错误或者用户执行了rollback语句,系统可以利用undo log中的备份将数据恢复到事务开始之前的状态。

注意:undo log是逻辑日志(记录的是逆向回滚的逻辑,而不是实际的值),可以理解为:

当delete一条记录的时候,undo log中会记录一条对应的insert记录
当insert一条记录的时候,undo log中会记录一条对应的delete记录
当update一条记录的时候,undo log中会记录一条对应的update记录
看图说话
在这里插入图片描述
到这一步,我们的执行的 SQL 语句已经被加载到 Buffer Pool 中了,然后开始更新这条语句,更新的操作实际是在Buffer Pool中执行的。

redo 日志文件:记录数据被修改后的样子(前滚日志)
保证事务的持久性
归属于InnoDB存储引擎
物理日志
和undo log相反,redo log日志记录的是新数据的备份。在事务提交前,数据只需要在redo log中持久化即可,系统可以根据redo log的内容,将所有的数据恢复到最新的状态。

在这里插入图片描述
截至目前,我们应该都熟悉了 MySQL 的执行器调用存储引擎是怎么将一条 SQL 加载到缓冲池和记录哪些日志的,流程如下:

准备更新一条 SQL 语句
MySQL(innodb)会先去缓冲池(Buffer Pool)中去查找这条数据,没找到就会去磁盘中查找,如果查找到就会将这条数据加载到缓冲池(Buffer Pool)中
在加载到 Buffer Pool 的同时,会将这条数据的原始记录保存到 undo 日志文件中
innodb 会在 Buffer Pool 中执行更新操作
更新后的数据会记录在 redo log buffer 中
上面说的步骤都是在正常情况下的操作,但是程序的设计和优化并不仅是为了这些正常情况而去做的,也是为了那些临界区和极端情况下出现的问题去优化设计的

这个时候如果服务器宕机了,那么缓存中的数据还是丢失了。真烦,竟然数据总是丢失,那能不能不要放在内存中,直接保存到磁盘呢?很显然不行,因为在上面也已经介绍了,在内存中的操作目的是为了提高效率。

此时,如果 MySQL 真的宕机了,那么没关系的,因为 MySQL 会认为本次事务是失败的,所以数据依旧是更新前的样子,并不会有任何的影响。

好了,语句也更新好了那么需要将更新的值提交啊,也就是需要提交本次的事务了,因为只要事务成功提交了,才会将最后的变更保存到数据库,在提交事务前仍然会具有相关的其他操作。

将 redo log buffer 中的数据持久化到磁盘中,就是将 redo log buffer 中的数据写入到 redo log 日志文件中,一般情况下,redo log buffer 数据写入磁盘的策略是立即刷入磁盘(具体策略情况在下面小总结出会详细介绍),上图

在这里插入图片描述
如果 redo log Buffer 刷入磁盘后,数据库服务器宕机了,那我们更新的数据怎么办?此时数据是在内存中,数据岂不是丢失了?不,这次数据就不会丢失了,因为 redo log buffer 中的数据已经被写入到磁盘了,已经被持久化了,就算数据库宕机了,在下次重启的时候 MySQL 也会将 redo 日志文件内容恢复到 Buffer Pool 中(这边我的理解是和 Redis 的持久化机制是差不多的,在 Redis 启动的时候会检查 rdb 或者是 aof 或者是两者都检查,根据持久化的文件来将数据恢复到内存中)

到此为止,从执行器开始调用存储引擎接口做了哪些事情呢?

1.准备更新一条 SQL 语句

2.MySQL(innodb)会先去缓冲池(BufferPool)中去查找这条数据,没找到就会去磁盘中查找,如果查找到就会将这条数据加载 到缓冲池(BufferPool)中

3.在加载到 Buffer Pool 的同时,会将这条数据的原始记录保存到 undo 日志文件中

4.innodb 会在 Buffer Pool 中执行更新操作

5.更新后的数据会记录在 redo log buffer 中

6.MySQL 提交事务的时候,会将 redo log buffer 中的数据写入到 redo log日志文件中 。刷磁盘的策略可以通过 innodb_flush_log_at_trx_commit 参数来设置

0:log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行。该模式下在事务提交的时候,不会主动触发写入磁盘的操作。

1:每次事务提交时MySQL都会把log buffer的数据写入log file,并且flush(刷到磁盘)中去,该模式为系统默认。

2:每次事务提交时MySQL都会把log buffer的数据写入log file,但是flush(刷到磁盘)操作并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操作。

7.myslq 重启的时候会将 redo log恢复到缓冲池中

截止到目前位置,MySQL 的执行器调用存储引擎的接口去执行【执行计划】提供的 SQL 的时候 InnoDB 做了哪些事情也就基本差不多了,但是这还没完。下面还需要介绍下 MySQL 级别的日志文件bin log

bin log 日志文件:记录整个操作过程
归属于MySql Server
逻辑日志
上面介绍到的redo log是 InnoDB 存储引擎特有的日志文件,而bin log属于是 MySQL 级别的日志。 redo log记录的东西是偏向于物理性质的,如:“对什么数据,做了什么修改”。bin log是偏向于逻辑性质的,类似于:“对 students 表中的 id 为 1 的记录租了更新操作” 两者的主要特点总结如下:

在这里插入图片描述

bin log文件是如何刷入磁盘的?
bin log的刷盘是有相关的策略的,策略可以通过sync_bin log来修改,默认为0,表示先写入 os cache,也就是说在提交事务的时候,数据不会直接到磁盘中,这样如果宕机bin log数据仍然会丢失。所以建议将sync_bin log设置为 1 表示直接将数据写入到磁盘文件中。

刷入bin log有以下几种模式

1、 STATMENT

基于 SQL 语句的复制(statement-based replication, SBR),每一条会修改数据的 SQL 语句会记录到 bin log 中

【优点】:不需要记录每一行的变化,减少了 bin log 日志量,节约了 IO , 从而提高了性能

【缺点】:在某些情况下会导致主从数据不一致,比如执行sysdate()、slepp()等

2、ROW

基于行的复制(row-based replication, RBR),不记录每条SQL语句的上下文信息,仅需记录哪条数据被修改了

【优点】:不会出现某些特定情况下的存储过程、或 function、或 trigger 的调用和触发无法被正确复制的问题

【缺点】:会产生大量的日志,尤其是 alter table 的时候会让日志暴涨

3、MIXED

基于 STATMENT 和 ROW 两种模式的混合复制( mixed-based replication, MBR ),一般的复制使用 STATEMENT 模式保存 bin log ,对于 STATEMENT 模式无法复制的操作使用 ROW 模式保存 bin log

那既然bin log也是日志文件,那它是在什么记录数据的呢?

其实 MySQL 在提交事务的时候,不仅仅会将 redo log buffer 中的数据写入到redo log 文件中,同时也会将本次修改的数据记录到 bin log文件中,同时会将本次修改的bin log文件名和修改的内容在bin log中的位置记录到redo log中,最后还会在redo log最后写入 commit 标记,这样就表示本次事务被成功的提交了。

在这里插入图片描述
如果在数据被写入到bin log文件的时候,刚写完,数据库宕机了,数据会丢失吗?

首先可以确定的是,只要redo log最后没有 commit 标记,说明本次的事务一定是失败的。但是数据是没有丢失了,因为已经被记录到redo log的磁盘文件中了。在 MySQL 重启的时候,就会将 redo log 中的数据恢复(加载)到Buffer Pool中。

好了,到目前为止,一个更新操作我们基本介绍得差不多,但是你有没有感觉少了哪件事情还没有做?是不是你也发现这个时候被更新记录仅仅是在内存中执行的,哪怕是宕机又恢复了也仅仅是将更新后的记录加载到Buffer Pool中,这个时候 MySQL 数据库中的这条记录依旧是旧值,也就是说内存中的数据在我们看来依旧是脏数据,那这个时候怎么办呢?

其实 MySQL 会有一个后台线程,它会在某个时机将我们Buffer Pool中的脏数据刷到 MySQL 数据库中,这样就将内存和数据库的数据保持统一了。
在这里插入图片描述
总结

到此,关于Buffer Pool、Redo Log Buffer 和undo log、redo log、bin log 概念以及关系就基本差不多了。

我们再回顾下

1.Buffer Pool 是 MySQL 的一个非常重要的组件,因为针对数据库的增删改操作都是在 Buffer Pool 中完成的
2.Undo log 记录的是数据操作前的样子
3.redo log 记录的是数据被操作后的样子(redo log 是 Innodb 存储引擎特有)
4.bin log 记录的是整个操作记录(这个对于主从复制具有非常重要的意义)
从准备更新一条数据到事务的提交的流程描述

1.首先执行器根据 MySQL 的执行计划来查询数据,先是从缓存池中查询数据,如果没有就会去数据库中查询,如果查询到了就将其放到缓存池中
2.在数据被缓存到缓存池的同时,会写入 undo log 日志文件
3.更新的动作是在 Buffer Pool 中完成的,同时会将更新后的数据添加到 redo log buffer 中
4.完成以后就可以提交事务,在提交的同时会做以下三件事:
1、将redo log buffer中的数据刷入到redo log文件中,prepare阶段(二阶段提交)

2、将本次操作记录写入到 bin log文件中

3、将bin log文件名字和更新内容在 bin log 中的位置记录到redo log中,同时在 redo log 最后添加 commit 标记,commit阶段(二阶段提交)

至此表示整个更新事务已经完成

relay log 日志文件:从库用来保存主库发过来bin log日志内容的文件
从服务器I/O线程将主服务器的bin log日志读取过来记录到从服务器本地文件relay log,然后从服务器SQL线程会读取relay log日志的内容并应用到从服务器,从而使从服务器和主服务器的数据保持一致。

在这里插入图片描述
主库db的更新事件(update、insert、delete)被写到binlog
从库发起连接,连接到主库
此时主库创建一个binlog dump thread,把binlog的内容发送到从库
从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log
还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/61979.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何通过 WordPress 数据库启用插件?【进不去后台可用】

如果您无法访问 WordPress 后台并需要激活插件以恢复访问权限,则可以通过 WordPress 数据库来实现。本文将向您展示如何使用数据库轻松激活 WordPress 插件。 何时使用数据库激活 WordPress 插件? 许多常见的 WordPress 错误会阻止网站所有者访问 WordP…

性能测试工具在提升软件质量和用户体验方面的关键作用

在当今的数字时代,软件应用的性能和响应速度对于用户体验和企业的成功至关重要。为了满足用户对高性能和卓越体验的期望,开发团队需要使用专业的性能测试工具来检测和改进应用程序的性能。本文将讨论性能测试工具在提升软件质量和用户体验方面的关键作用…

Python 模块 locust 性能测试

简介 locust 是 Python 的一个开源的负载测试工具,用于测试网络应用程序的性能和可伸缩性。它使用Python编写,并提供了一个简单易用的语法来定义和执行负载测试。locust模块允许用户模拟大量并发用户并观察系统在高负载下的响应情况。 目录 1. 基本用法…

Spring5.2.x 源码使用Gradle成功构建

一 前置准备 1 Spring5.2.x下载 1.1 Spring5.2.x Git下载地址 https://gitcode.net/mirrors/spring-projects/spring-framework.git 1.2 Spring5.2.x zip源码包下载,解压后倒入idea https://gitcode.net/mirrors/spring-projects/spring-framework/-/…

Layui实现OA会议系统之会议管理模块总合

目录 一、项目背景 二、项目概述 1. 概述 2. 环境搭建 3. 工具类引用 4. 功能设计 4.1 会议发布 4.2 我的会议 4.3 会议审批 4.4 会议通知 4.5 待开会议 4.6 历史会议 4.7 所有会议 5. 性能优点 5.1 兼容性好 5.2 可维护性和可扩展性 5.3 轻量灵活 5.4 模块化设计…

[BabysqliV3.0]phar反序列化

文章目录 [BabysqliV3.0]phar反序列化 [BabysqliV3.0]phar反序列化 开始以为是sql注入 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ST1jvadM-1691302941344)(https://raw.githubusercontent.com/leekosss/photoBed/master/202308032140269.png)…

SQL-每日一题【1179. 重新格式化部门表】

题目 部门表 Department: 编写一个 SQL 查询来重新格式化表,使得新的表中有一个部门 id 列和一些对应 每个月 的收入(revenue)列。 查询结果格式如下面的示例所示: 解题思路 1.题目要求我们重新格式化表,…

【Linux】五、进程

一、冯诺依曼体系结构 存储器:指的是内存; 输入设备:键盘、摄像头、话筒,磁盘,网卡; 输出设备:显示器、音响、磁盘、网卡; 中央处理器(CPU):运算器…

一、8.分页

当物理内存不够时就把不常用的内存暂时存入磁盘,并且描述符的P位置0,把要使用的段放入内存,描述符P位置1 但是这种方式会产生大量内存碎片,影响内存分配效率 设想一个虚拟内存,每隔任务都有他独立的虚拟内存&#xf…

【编译原理】五、简单四则运算的代码实现

1. 前言 前面说了那么多BNF的相关理论知识,实际上就是为了一个目的: 描述语法规则 描述语法规则是一切的开始。最终,还是要用代码来实现。 如果对于BNF仍然是一头雾水,也没关系,因为我们的最终目的是编写解析器&…

用Abp实现找回密码和密码强制过期策略

用户找回密码,确切地说是重置密码,为了保证用户账号安全,原始密码将不再以明文的方式找回,而是通过短信或者邮件的方式发送一个随机的重置校验码(带校验码的页面连接),用户点击该链接&#xff0…

.dex文件转换成.class文件,.class文件转成java文件

.dex文件转换成.class文件 什么是.dex文件 dex文件是Android系统的可执行文件,包含应用程序的全部操作指令以及运行时数据。 由于dalvik是一种针对嵌入式设备而特殊设计的java虚拟机,所以dex文件与标准的class文件在结构设计上有着本质的区别。 当java程序编译成class后,还需…

解决一个Sqoop抽数慢的问题,yarn的ATSv2嵌入式HBASE崩溃引起

新搭建的一个Hadoop环境,用Sqoop批量抽数的时候发现特别慢,我们正常情况下是一个表一分钟左右,批量抽十几个表,也就是10分钟的样子,结果发现用了2个小时: 查看yarn日志 发现有如下情况: 主要有两…

《JeecgBoot系列》JeecgBoot(ant-design-vue) 识别字段中指定内容并修改该行文字颜色

JeecgBoot(ant-design-vue) 识别字段中指定内容并修改该行文字颜色 需求&#xff1a;将生产工厂是配件工厂的行改变颜色标注 一、修改table组件内容 在<a-table></a-table>内添加:rowClassName"tableRowClass" <a-table>...:rowClassName"t…

动态路由协议 ospf

动态路由协议的分类 rip : 距离矢量路由协议&#xff08;容易产生环路&#xff09;ospf&#xff1a; 链路状态路由协议&#xff08;比较耗费资源&#xff0c;但是链路准确性好&#xff09;bgp&#xff1a; 外部网关协议 RIP OSPF LSA泛洪 LSDB维护 SPF计算&#xff08;最短路…

前端笔记html-layer使用

layer.open方法 layer.open({type:2, //可传入的值有&#xff1a;0&#xff08;信息框&#xff0c;默认&#xff09;1&#xff08;页面层&#xff09;2&#xff08;iframe层&#xff09;3&#xff08;加载层&#xff09;4&#xff08;tips层&#xff09;title: title,content:[…

postgis mvt矢量切片 django drf mapboxgl

postgis mvt矢量切片 django drf mapboxgl 目录 0.前提 1.sql代码 2.django drf后端服务代码 3.具体的应用&#xff08;整体代码&#xff09; 4.参考 0.前提 [1] 静态的矢量切片可以采用 tippecanoe 生成&#xff0c;nginx代理&#xff0c;这种数据是不更新的&#xff1b…

Element的Dialog+Form使用问题

在Element的Dialog中使用表单时&#xff0c;可能会出现以下问题 无法清空表单校验 <el-dialog title"新建资产" :visible.sync"addAssetsFormVisible" close"resetForm(addAssets)">resetForm (formName) {this.$refs[formName].resetFie…

LeetCode724. 寻找数组的中心下标

题干 给你一个整数数组 nums &#xff0c;请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标&#xff0c;其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端&#xff0c;那么左侧数之和视为 0 &#xff0c;因为在下标的左侧不存在元素。…

高德地图实现点聚合功能的详细步骤

目录 介绍准备工作1.注册并登录高德地图开放平台&#xff0c;申请密钥2.在Vue项目中安装高德地图的相关库/插件。 一、点聚合1.引入高德地图API<font color purple>initializeMap()<font color purple>loadData()<font color purple>createMarkerClustere…