MySQL(3)-日志
3. InnoDB日志
3.1 InnoDB架构

分为
- 内存区域架构
- buffer pool
- log buffer
- 磁盘区域架构
- redo log
- undo log
2.1.1 内存区域架构
1)Buffer Pool
定义
InnoDB对会将磁盘中经常访问的数据所在的页存入Buffer Pool中以加快访问速度,这种操作称为预读,后续对磁盘上某条数据做修改时,也是先读取到buffer pool中,再修改buffer pool中的数据
组成
由多个Page组成,其中存储了磁盘上的多行数据,方便了大容量的高效读操作,此外,将Page组织成链表结构,便于采用LRU进行内存淘汰
2)Change Buffer
定义
对于非唯一索引,如果在修改其对应的数据时,行记录不存在于Buffer Pool,那么就将修改操作记录到Change Buffer,等待后面真正读取到该记录到Buffer Pool中时,再将结果进行merge,并修改磁盘中的数据
为何必须非唯一
对于唯一索引,InnoDB需要对记录的唯一性做校验,也就必须从磁盘中读取到数据,而change buffer的存在意义是尽量避免不必要的随机磁盘io,而对于唯一性校验来说,磁盘io是不可避免的,且由于唯一索引b+树的特点,在是自增的情况下,插入操作是一次顺序io,效率是很高的,也就不必有change buffer
3)自适应哈希索引
定义
为了让MySQL性能更接近于基于内存的数据库,对于经常访问的数据,会根据数据的特点,以表的某几列建立hash索引,存储结构类似于hashmap,采用拉链法解决hash冲突,使得查询复杂度降低到O(1)
特性
- 优
- 适应等值比较
- 适应单条数据查询
- 劣
- 不适应范围查询
- 不可用范围或like比较
- 不适用连表查询
- 优
4)Log Buffer
是磁盘上log文件的缓冲区,修改会先记录到此buffer,之后异步的同步到磁盘上的log文件
3.1.2 磁盘区域架构
除了表、索引、表空间之外还有
1)Doublewrite Buffer
buffer pool中对页面的修改信息不会直接同步到对应的表中,而是会以大的连续块的形式调用fsync()写入到双写缓存中,这样在os、存储引擎或其他异常发生时,可以从双写缓存中找到备份
2)redo log
3)undo log
3.2 bin log&redo log&undo log
3.2.1 binlog
1)组成
binlog cache
作为binlog的缓存,会先写入cache中
binlog-xxx
存在于磁盘上的binlog文件,是append only式创建
2)存储内容
可以配置成三种类型
statement
记录为逻辑日志,存储提交的事务的DML语句和事务号
row
记录为物理日志,记录了实际的修改,会使得日志比较大
mixed
前两者的结合
3)作用
多用于主从同步和冷备
4)层级
位于MySQL server层
3.2.2 redo log
1)组成
redo log buffer
作为redo log的缓存,会先写入cache中
ib_logfile-xxx
存在于磁盘上的redo log文件,是循环写入的,对于已经提交的事务,会清空
2)存储内容
是物理日志和逻辑日志的结合,物理体现在记录了具体某一页上发生了修改,逻辑体现在页内的实际修改是以记录DML语句完成的
3)作用
用于宕机恢复,保证一致性
4)层级
位于存储引擎层
3.2.3 undo log
1)组成
undo log
update log
对于未提交的事务内发生的update操作,会存储相反的update
insert log
对于未提交的事务内发生的delete操作,会存储对应的insert
delete log
对于未提交的事务内发生的insert操作,会存储对应的delete
上述log会以事务号的顺序编排成一个链表以便于确定要回滚到哪个事务
2)存储内容
是逻辑日志,存储相反的DML语句
3)作用
用于回滚,保证原子性
4)层级
位于存储引擎层
3.3 事务内修改流程
假设事务内存在一条insert语句,那么实际执行流程如下
- 导入buffer并修改
- 记录undo log
- 记录redo log buffer并写盘
- 2PC提交
详细流程如下
3.3.1 导入buffer并修改
检查buffer pool中是否存在要更新的数据所在的页,如果不存在,需要将页面读入buffer pool,之后修改对应的数据
3.3.2 记录undo log
将delete语句记录到磁盘中的undo log,组织成链表
3.3.3 记录redo log buffer并写盘
将修改记录到buffer,之后根据写盘策略,将buffer中的数据写入到redo log,同步的策略有下面三种,通过设定innodb_flush_log_at_trx_commit完成
0
每次提交都写入redo log buffer,之后每秒执行
fsync()同步到redo log1
每次提交都直接写入到redo log中
2
每次提交写入os cache,之后根据
innodb_flush_log_at_timeout配置,决定多久后fsync()
3.3.4 2PC提交
1)流程
由于InnoDB的redo log出现晚于binlog,且两者都用于crash safe,那么就需要保证binlog和redolog中数据的一致性,这里采用类似于分布式事务中的想法,采用两阶段提交的方式来保证一致性,流程如下(此时默认redo log写盘已经执行)
进入Prepare阶段,设置redo log为prepare
写入binlog cache
进入Commit阶段,设置redo log为commit
根据binlog的写盘策略,将binlog cahce写入binlog,策略有下面三种
0
每次提交写入到os cache
1
每次提交都直接写入bin log
N
每次都写入os cache,累计N个事务再
fsync()
2)异常分析
写redo log宕机
这时可以根据已经落盘的undo log进行回滚
写binlog cache宕机
这时一致性未达成,根据undo log做回滚
提交后宕机
检查redo log中存储的最新事务号是否存在于binlog,如果不存在,将不存在的回滚
3.4 预写日志
预写日志(Write Ahead Log)即在修改磁盘内的数据页中的信息前,将修改信息先写入磁盘中的log文件,如redo log和bin log
这么做有以下优势
顺序io
由于redo log和binlog落盘时是顺序写入的,而如果直接修改磁盘中数据页中的数据,是随机io,效率非常低
并发量大
读写者互不阻塞
fsync调用次数少
相较于直接写入磁盘,WAL的fsync调用次数很少,无需每个事务都写盘
3.5 sync、fsync和fdatasync
3.5.0 延迟写
linux中为了减少磁盘io,在写入磁盘时会经历如下步骤
- 写入os cache
- 写入output queue
- 写入磁盘
只有当os cache满时,才会复制到output queue;只有output queue队首的数据会被写入到磁盘
3.5.1 sync
将数据同步到os cache,并不会等待到写入磁盘后返回,这需要update守护进程周期性调用sync将os cache输出到output queue保证写盘成功
3.5.2 fsync
对于某个文件的fd,调用fsync会在写盘成功后返回,写入的数据包括inode中的文件属性以及文件的数据部分
3.5.3 fdatasync
同样对于某个文件的fd,调用fdatasync会在写盘成功后返回,写入的数据只有文件的数据部分,不包括inode
3.6 double write和redo log
3.6.1 为何需要Doublewrite
buffer pool中的数据要写入到磁盘时,是以页为单位,如果写入过程出现宕机,那么就算有redo log也无法恢复,由于redo log每个页内记录的是逻辑日志,而逻辑日志需要保证表中的数据是完备且未改动的,这样where条件才不会失效,因而redo log并不能保证页面级别的crash safe
3.6.2 Doublewrite实现
1)组成
分为两部分
- 内存中的double write buffer
- 物理磁盘上共享表空间中连续的128个页,即2个区(extent),大小同样为2MB
2)机制
流程如下
- 每次脏页会先复制到double write buffer
- 分两次,每次1MB将页面信息书顺序写入到磁盘上的共享表空间
- 将buffer中的数据调用fsync离散写入磁盘
这样由于在磁盘的共享表空间中记录了页面的详细修改信息,就可以在同步页面到磁盘上时保证crash safe
# 参考
MySQL :: MySQL 5.7 Reference Manual :: 14.4 InnoDB Architecture
为什么数据不会丢,InnoDB的Double Write,你必须知道 - 掘金 (juejin.cn)
MySQL--buffer pool、redo log、undo log、binlog_黄智霖的博客-CSDN博客
Write-Ahead Logging (sqlite.org)
redo log的被动刷盘机制 - 云+社区 - 腾讯云 (tencent.com)
Linux IO同步函数:sync、fsync、fdatasync | Byte_Liu's Blog (byteliu.com)
MySQL(3)-日志的更多相关文章
- MySQL错误日志总结
MySQL错误日志是记录MySQL 运行过程中较为严重的警告和错误信息,以及MySQL每次启动和关闭的详细信息.错误日志的命名通常为hostname.err.其中,hostname表示服务器主机名. ...
- mysql数据库服务日志
mysql数据库服务日志 ①. 错误日志:error_log ②. 普通日志:general_log ③. 慢查询日志:log-slow-query #有3个参数 分割:.mv .编写定时任务并执行: ...
- mysql 二进制日志后缀数字最大为多少
之前看到mysql二进制日志后面会加一个以数字递增为结尾的后缀,一直在想当尾数到达999999后会发生什么情况,先查了一下官网,对后缀有这样一句介绍:The server creates binary ...
- MySQL慢日志监控脚本实例剖析
公司线上的 MySQL 慢日志,之前一直没有做好监控.趁着上周空闲,我就把监控脚本写了下,今天特地把代码发出来与51博友分享一下. 针对脚本的注解和整体构思,我会放到脚本之后为大家详解. 1 2 3 ...
- MySQL二进制日志的备份和恢复
二进制日志:记录数据库修改的相关操作,作用是即时点回复,主从复制 可以按时间滚动,也可以按大小滚动 server-id:服务器身份标识 一.二进制文件的删除方法,千万不要手动删除 PURGE BINA ...
- mysql 的日志文件
mysql的日志文件 日志文件大致分为 error log, binary log, query log, slow query log, innodb redo log ;如图: 1.error ...
- [转载]mysql慢日志文件分析处理
原文地址:mysql慢日志文件分析处理作者:maxyicha mysql有一个功能就是可以log下来运行的比较慢的sql语句,默认是没有这个log的,为了开启这个功能,要修改my.cnf或者在mysq ...
- ELK监控系统nginx / mysql慢日志
ELK监控系统nginx / mysql慢日志 elasticsearch logstash kibana ELK监控系统nginx日志 1.环境准备 centos6.8_64 mini IP:192 ...
- MySQL 错误日志(Error Log)
同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件.通常包括错误日志文件,二进制日志,通用日志,慢查询日志,等等. 这些日志能够帮助我们定位mysqld ...
- Mysql Binlog日志详解
一.Mysql Binlog格式介绍 Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在 ...
随机推荐
- Java异常02——自定义异常
Error与Exception与自定义异常 Error与Exception Error Exception 自定义异常 快捷键: ctrl + alt + t package exception.d ...
- Android Jetpack 架构组件最佳实践之“网抑云”APP
背景 近几年,Android 相关的新技术层出不穷.往往这个技术还没学完,下一个新技术又出来了.很多人都是一脸黑人问号? 不少开发者甚至开始哀嚎:"求求你们别再创造新技术了,我们学不动了!& ...
- ReentrantLock 中的 4 个坑!
JDK 1.5 之前 synchronized 的性能是比较低的,但在 JDK 1.5 中,官方推出一个重量级功能 Lock,一举改变了 Java 中锁的格局.JDK 1.5 之前当我们谈到锁时,只能 ...
- Java 多线程与并发【知识点笔记】
Java 多线程与并发[知识点笔记] Java多线程与并发 先说一下线程与进程的由来: 在初期的计算机,计算机只能串行执行任务,并且需要长时间的等待用户的输入才行 到了后来,出现了批处理,可以预先将用 ...
- 从net到java:MyBatis快速入门
第一:这不是net与java的对比,只是我学习java相关知识梳理的笔记. 第二:这也没有否认net,只是现在的工作需要自己会java. 第三:这不深入.只是我看了些官网和网上的视频,算是入门的总结. ...
- 为什么网络损伤仪WANsim中没有流量通过
在使用网络损伤仪 WANsim 的过程中,有时候发现网损仪中没有流量通过.有些小伙伴可能会想:自己所有配置都是正确的 ,为什么会没有流量通过呢? 有可能,是你忽略了一些东西. 下面,我总结了一些导致网 ...
- NOIP 模拟 $32\; \rm Smooth$
题解 \(by\;zj\varphi\) 很简单的贪心题. 开 \(B\) 个队列,每个队列存最后一次乘上的数为当前队列编号的数. 每次去所有队列中队首的最小值,不用开堆,因为开堆用于将所有数排序,但 ...
- express中session的基本使用
1.首先安装express-session模块 npm install express-session --save 2.引入express-session,以及设置中间键 var session = ...
- 综合练习——寻找有潜力的bilibili百大UP主(1)
寻找有潜力的bilibili百大UP主(1) 防喷说明:以下仅为个人学习之余的娱乐项目,本人不主动赋予以下内容任何价值,不确保内容的准确性 欢迎各位友善的指出错误 目录 寻找有潜力的bilibili百 ...
- C# prism 框架 MVVM框架 Prism系列之事件聚合器
网址:https://www.cnblogs.com/ryzen/p/12610249.html 本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的使用事件聚合器实现模块间的通信 ...