innodb事务日志详解
首先看InnoDB的缓存和文件的关系图如下:
InnoDB事务日志功能介绍
InnoDB使用日志来减少提交事务时的开销。因为日志中已经记录了事务,就无须在每个事务提交时把缓冲池的脏块刷新(flush)到磁盘中。事务修改的数据和索引通常会映射到表空间的随机位置,所以刷新这些变更到磁盘需要很多随机IO。InnoDB假设使用常规磁盘,随机IO比顺序IO昂贵得多,因为一个IO请求需要时间把磁头移到正确的位置,然后等待磁盘上读出需要的部分,再转到开始位置。
日志把随机IO变成顺序IO
InnoDB用日志把随机IO变成顺序IO。一旦日志安全写到磁盘,事务就持久化了,即使断电了,InnoDB可以重放日志并且恢复已经提交的事务。
InnoDB使用一个后台线程智能地刷新这些变更到数据文件。这个线程可以批量组合写入,使得数据写入更顺序,以提高效率。
日志文件大小配置
整体的日志文件大小受控于innodb_log_file_size和innodb_log_files_in_group两个参数,这对写性能非常重要。日志文件的总大小是每个文件的大小之和。
- innodb_log_files_in_group:DB中设置几组事务日志,默认是2;
- innodb_log_file_size:控制事务日志ib_logfile的大小,范围5MB~4G;所有事务日志ib_logfile0+ib_logfile1+..累加大小不能超过4G,事务日志大,checkpoint会少,节省磁盘IO,但是大的事务日志意味着数据库crash时,恢复起来较慢。
引入问题:修改该参数大小,导致ib_logfile文件的大小和之前存在的文件大小不匹配
解决方式:在干净关闭数据库情况下,删除ib_logfile,而后重启数据库,会自行创建该文件;
InnoDB使用多个文件作为一组循环日志。通常不需要修改默认的日志数量,只修改每个日志文件的大小即可。要修改日志文件大小,需要完全关闭MySQL,将旧的日志文件移到其他地方保存,重新配置参数。
日志文件大小和日志缓存
要确定理想的日志文件大小,必须权衡正常数据变更的开销和崩溃恢复需要的时间,如果日志太小,InnoDB必然将做更多的检查点,导致更多的日志写。如果日志太大,在崩溃恢复时InnoDB可能不得不做大量的工作。
当InnoDB变更任何数据时,会写一条变更记录到内存日志缓冲区中。在缓冲满的时候,事务提交的时候,或者每一秒钟,这三个条件无论哪个先达到,InnoDB都会刷新缓冲区的内容到磁盘日志文件。变量innodb_log_buffer_size可以控制日志缓冲区的大小,默认为1M。通常不需要把日志缓冲区设置得非常大。推荐的范围是1~8M。作为一个经验法则,日志文件的全部大小,应该足够容纳服务器一个小时的活动内容。
InnoDB怎么刷新日志缓冲?当InnoDB把日志缓冲刷新到磁盘日志文件时,会先使用一个Mutex锁住缓冲区,刷新到所需要的位置,然后移动剩下的条目到缓冲区的前面。日志缓冲必须被刷新到持久化存储,以确保提交的事务完全被持久化了。如果和持久相比更在乎性能,可以修改innodb_flush_log_at_trx_commit变量来控制日志缓冲刷新的频繁程度,有如下3个值可以设置,安全递增:0,2,1
- 0:每秒一次把日志缓冲写到日志文件,但是事务提交时不做任何时。
- 1:将日志缓冲写到日志文件,然后每次事务提交都刷新到持久化存储(默认并且最安全的设置),该设置保证不会丢失任何已提交的事务。
- 2:每秒钟做一次刷新,但每次提交时把日志缓冲写到日志文件,但是不刷新到持久化存储。
“把日志缓冲写到日志文件”和“把日志刷新到持久化存储”是不同的。在大部分操作系统中,把缓冲写到日志只是简单地把数据从InnoDB的内存缓冲转移到了操作系统的缓存,也是在内存里,并没有真正把数据写到持久化存储。
如果MySQL崩溃了或者断电了,设置0和2通常会导致最多秒的数据丢失,因为数据可能存在于操作系统的缓存中。
相反,把日志刷新到持久化存储意味着InnoDB请求操作系统把数据刷出缓存,并且确认写到磁盘了,这是一个阻塞IO的调用,直到数据被完全写回才会完成,当写数据到磁盘比较慢,而该配置项设置为1时,可能明显地降低InnoDB每秒可以提交的事务数。
InnoDB如何保证事务的
MySQL会最大程度的使用缓存机制来提高数据库的访问效率,但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据丢失而导致数据不一致怎么办?
Innodb主要是通过事务日志实现ACID特性
事务日志包括:重做日志redo和回滚日志undo
Redo记录的是已经全部完成的事务,就是执行了commit的事务,记录文件是ib_logfile0 ib_logfile1
Undo记录的是已部分完成并且写入硬盘的未完成的事务,默认情况下回滚日志是记录下表空间中的(共享表空间或者独享表空间)
一般情况下,mysql在崩溃之后,重启服务,innodb通过回滚日志undo将所有已完成并写入磁盘的未完成事务进行rollback,然后redo中的事务全部重新执行一遍即可恢复数据,但是随着redo的量增加,每次从redo的第一条开始恢复就会浪费长的时间,所以引入了checkpoint机制
Dirty page:脏页 什么意思呢?
一般业务运行过程中,当业务需要对某张的某行数据进行修改的时候,innodb会先将该数据从磁盘读取到缓存中去,然后在缓存中对这条数据进行修改,这样缓存中的数据就和磁盘的数据不一致了,这个时候缓存中的数据就称为dirty page,只有当脏页统一刷新到磁盘中才会是clean page
Checkpoint:如果在某个时间点,脏页的数据被刷新到了磁盘,系统就把这个刷新的时间点记录到redo log的结尾位置,在进行恢复数据的时候,checkpoint时间点之前的数据就不需要进行恢复了,可以缩短时间
Innodb_log_buffer_size 重做日志缓存大小
Innodb_log_file_size redo log文件大小 文件越大 数据恢复的时间越长
Innodb_log_file_group redo log文件数量 默认是2个 ib_logfile0 ib_logfile1
mysql innoDB日志机制深入
Innodb的事务日志是指Redo log,保存在日志文件ib_logfile*里面。Innodb还有另外一个日志Undo log,但Undo log是存放在共享表空间里面的(ibdata*文件)。
名词解释:LSN,日志序列号,Innodb的日志序列号是一个64位的整型。
Log写入
LSN实际上对应日志文件的偏移量,新的LSN=旧的LSN + 写入的日志大小。举例如下:
LSN=1G,日志文件大小总共为600M,本次写入512字节,则实际写入操作为:
l 求出偏移量:由于LSN数值远大于日志文件大小,因此通过取余方式,得到偏移量为400M;
l 写入日志:找到偏移400M的位置,写入512字节日志内容,下一个事务的LSN就是1000000512;
Checkpoint写入
Innodb实现了Fuzzy Checkpoint的机制,每次取到最老的脏页,然后确保此脏页对应的LSN之前的LSN都已经写入日志文件,再将此脏页的LSN作为Checkpoint点记录到日志文件,意思就是“此LSN之前的LSN对应的日志和数据都已经写入磁盘文件”。恢复数据文件的时候,Innodb扫描日志文件,当发现LSN小于Checkpoint对应的LSN,就认为恢复已经完成。
Checkpoint写入的位置在日志文件开头固定的偏移量处,即每次写Checkpoint都覆盖之前的Checkpoint信息。
管理机制
由于Checkpoint和日志紧密相关,将日志和Checkpoint一起说明,详细的实现机制如下:
如上图所示,Innodb的一条事务日志共经历4个阶段:
l 创建阶段:事务创建一条日志;
l 日志刷盘:日志写入到磁盘上的日志文件;
l 数据刷盘:日志对应的脏页数据写入到磁盘上的数据文件;
l 写CKP:日志被当作Checkpoint写入日志文件;
对应这4个阶段,系统记录了4个日志相关的信息,用于其它各种处理使用:
l Log sequence number(LSN1):当前系统LSN最大值,新的事务日志LSN将在此基础上生成(LSN1+新日志的大小);
l Log flushed up to(LSN2):当前已经写入日志文件的LSN;
l Oldest modified data log(LSN3):当前最旧的脏页数据对应的LSN,写Checkpoint的时候直接将此LSN写入到日志文件;
l Last checkpoint at(LSN4):当前已经写入Checkpoint的LSN;
对于系统来说,以上4个LSN是递减的,即: LSN1>=LSN2>=LSN3>=LSN4.
具体的样例如下(使用show innodb status /G命令查看,Oldest modified data log没有显示):
保护机制
Innodb的数据并不是实时写盘的,为了避免宕机时数据丢失,保证数据的ACID属性,Innodb至少要保证数据对应的日志不能丢失。对于不同的情况,Innodb采取不同的对策:
l 宕机导致日志丢失
Innodb有日志刷盘机制,可以通过innodb_flush_log_at_trx_commit参数进行控制;
l 日志覆盖导致日志丢失
Innodb日志文件大小是固定的,写入的时候通过取余来计算偏移量,这样存在两个LSN写入到同一位置的可能,后面写的把前面写得就覆盖了,以“写入机制”章节的样例为例,LSN=100000000和LSN=1600000000两个日志的偏移量是相同的了。这种情况下,为了保证数据一致性,必须要求LSN=1000000000对应的脏页数据都已经刷到磁盘中,也就是要求Last checkpoint对应的LSN一定要大于1000000000,否则覆盖后日志也没有了,数据也没有刷盘,一旦宕机,数据就丢失了。
为了解决第二种情况导致数据丢失的问题,Innodb实现了一套日志保护机制,详细实现如下:
上图中,直线代表日志空间(Log cap,约等于日志文件总大小*0.8,0.8是一个安全系数),Ckp age和Buf age是两个浮动的点,Buf async、Buf sync、Ckp async、Ckp sync是几个固定的点。各个概念的含义如下:
概念 |
计算 |
含义 |
Ckp age |
LSN1- LSN4 |
还没有做Checkpoint的日志范围,若Ckp age超过日志空间,说明被覆盖的日志(LSN1-LSN4-Log cap)对应日志和数据“可能”还没有刷到磁盘上 |
Buf age |
LSN1- LSN3 |
还没有将脏页刷盘的日志的范围,若Buf age超过日志空间,说明被覆盖的日志(LSN1-LSN3-Log cap)对应数据“肯定”还没有刷到磁盘上 |
Buf async |
日志空间大小 * 7/8 |
强制将Buf age-Buf async的脏页刷盘,此时事务还可以继续执行,所以为async,对事务的执行速度没有直接影响(有间接影响,例如CPU和磁盘更忙了,事务的执行速度可能受到影响) |
Buf sync |
日志空间大小 * 15/16 |
强制将2*(Buf age-Buf async)的脏页刷盘,此时事务停止执行,所以为sync,由于有大量的脏页刷盘,因此阻塞的时间比Ckp sync要长。 |
Ckp async |
日志空间大小 * 31/32 |
强制写Checkpoint,此时事务还可以继续执行,所以为async,对事务的执行速度没有影响(间接影响也不大,因为写Checkpoint的操作比较简单) |
Ckp sync |
日志空间大小 * 64/64 |
强制写Checkpoint,此时事务停止执行,所以为sync,但由于写Checkpoint的操作比较简单,即使阻塞,时间也很短 |
当事务执行速度大于脏页刷盘速度时,Ckp age和Buf age会逐步增长,当达到async点的时候,强制进行脏页刷盘或者写Checkpoint,如果这样做还是赶不上事务执行的速度,则为了避免数据丢失,到达sync点的时候,会阻塞其它所有的事务,专门进行脏页刷盘或者写Checkpoint。
因此从理论上来说,只要事务执行速度大于脏页刷盘速度,最终都会触发日志保护机制,进而将事务阻塞,导致MySQL操作挂起。
由于写Checkpoint本身的操作相比写脏页要简单,耗费时间也要少得多,且Ckp sync点在Buf sync点之后,因此绝大部分的阻塞都是阻塞在了Buf sync点,这也是当事务阻塞的时候,IO很高的原因,因为这个时候在不断的刷脏页数据到磁盘。例如如下截图的日志显示了很多事务阻塞在了Buf sync点:
附注:Innodb的日志保护机制实现可以参考log0log.c文件的void log_check_margins(void)函数。
转自:http://blog.csdn.net/yunhua_lee/article/details/6567869
innodb事务日志详解的更多相关文章
- MySql中innodb存储引擎事务日志详解
分析下MySql中innodb存储引擎是如何通过日志来实现事务的? Mysql会最大程度的使用缓存机制来提高数据库的访问效率,但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据 ...
- 【夯实Mysql基础】MySQL在Linux系统下配置文件及日志详解
本文地址 分享提纲: 1. 概述 2. 详解配置文件 3. 详解日志 1.概述 MySQL配置文件在Windows下叫my.ini,在MySQL的安装根目录下:在Linux下叫my.cnf,该文件位于 ...
- MySQL 日志详解
一.MySQL 日志分类 MySQL 日志主要包含:错误日志.查询日志.慢查询日志.事务日志.二进制日志. 错误日志: -log-err (记录启动.运行.停止 MySQL 服务时出现的信息) 查询日 ...
- Net Core中数据库事务隔离详解——以Dapper和Mysql为例
Net Core中数据库事务隔离详解--以Dapper和Mysql为例 事务隔离级别 准备工作 Read uncommitted 读未提交 Read committed 读取提交内容 Repeatab ...
- 0614MySQL的InnoDB索引原理详解
转自http://www.cnblogs.com/shijingxiang/articles/4743324.html MySQL的InnoDB索引原理详解 http://www.admin10000 ...
- Spark小课堂Week6 启动日志详解
Spark小课堂Week6 启动日志详解 作为分布式系统,Spark程序是非常难以使用传统方法来进行调试的,所以我们主要的武器是日志,今天会对启动日志进行一下详解. 日志详解 今天主要遍历下Strea ...
- MySQL日志文件之错误日志和慢查询日志详解
今天天气又开始变得很热了,虽然很热很浮躁,但是不能不学习,我在北京向各位问好.今天给大家分享一点关于数据库日志方面的东西,因为日志不仅讨厌而且还很重要,在开发中时常免不了与它的亲密接触,就在前几天公司 ...
- Redis的事务功能详解
Redis的事务功能详解 MULTI.EXEC.DISCARD和WATCH命令是Redis事务功能的基础.Redis事务允许在一次单独的步骤中执行一组命令,并且可以保证如下两个重要事项: >Re ...
- (转)Spring事务管理详解
背景:之前一直在学习数据库中的相关事务,而忽略了spring中的事务配置,在阿里面试时候基本是惨败,这里做一个总结. 可能是最漂亮的Spring事务管理详解 https://github.com/Sn ...
随机推荐
- php变量简单介绍
1.isset() 判断变量是否存在 ==================================================================== 2.unset()清除变 ...
- [转]类不平衡问题与SMOTE过采样算法
在前段时间做本科毕业设计的时候,遇到了各个类别的样本量分布不均的问题——某些类别的样本数量极多,而有些类别的样本数量极少,也就是所谓的类不平衡(class-imbalance)问题. 本篇简述了以下内 ...
- Python 数据分析练习1
环境 Anaconda3 Python 3.6, Window 64bit 目的 从MySQL数据库读取数据,进行数据清理,数据展示 代码 # -*- coding: utf-8 -*- import ...
- SessionUtils
import com.diyfintech.constant.Constant.SuperAdmin; import com.diyfintech.pojo.SysUser; import org.a ...
- f5 ddos cc——Mitigating DDoS Attacks with F5 Technology
摘自:https://f5.com/resources/white-papers/mitigating-ddos-attacks-with-f5-technology Mitigating Appli ...
- SpringBoot_11_将springboot项目部署到外部tomcat上
一.前言 二. 三.参考资料 如何将Spring Boot项目打包部署到外部Tomcat 2.SpringBoot 项目如何在tomcat容器中运行
- 条款32:确定public继承中塑造出来的是IS-A关系而不是其他的关系
首先考虑的是一个很典型的关系,就是矩形与正方形的关系: class Recantagle{ virtual void setHeight(int); virtual void setWidth(int ...
- Java(Android)线程池妙用
介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new T ...
- 《Java程序员职场全攻略 从小工到专家》 - 书摘精要
(前言) 学习招式在次,提升内力才是最主要的: (P10) 选择一门编程语言,只是入门的途径.过分依赖编程语言,只会让自己成为代码高手,而不是开发大牛,要知道编程语言只是一种工具,更重要的是编程思想: ...
- L133
The U.S. Food and Drug Administration is considering a ban on flavorede-cigarettes in response to an ...