JavaGuide知识点整理——MySQL三大日志(binlog,redo log,undo log))

MySQL日志主要包括错误日志,查询日志,慢查询日志,事务日志,二进制日志几大类。其中比较重要的还属于二进制日志binlog(归档日志)和事务日志redo log(重做日志)和undo log(回滚日志)。
这篇文章就聊聊redo log,bin log,两阶段提交,undo log.

redo log(重做日志)

redo log(重做日志)是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复的能力。
比如MySQL实例挂了或者宕机了,重启时InnoDB存储引擎会使用redo log恢复数据。保证数据的持久性与完整性。


image.png

MySQL中数据是以页为单位,查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到Buffer Pool中。
后续的查询都先从Buffer Pool中找,如果没有命中再去硬盘加载,减少硬盘IO开销,提升性能。
更新表数据的时候,也是如此,发现Buffer Pool里存在要更新的数据,就直接在Buffer Pool里更新。
然后会把某个数据页上做了什么修改 记录到重做日志缓存(redo log buffer)里,接着刷盘到redo log文件里。


重做日志

理想情况下,事务一提交就会进行刷盘操作,但是实际上,刷盘的实际是根据策略来进行的。

刷盘时机

InnoDB存储引擎为redo log的刷盘策略提供了innodb_flush_log_at_trx_commit参数,它支持三种策略:

  • 0:设置为0时,每次事务提交不进行刷盘操作
  • 1:设置为1时,每次事务提交都进行刷盘操作(默认)
  • 2: 设置为2时,每次事务提交都只把redo log buffer内容写入page cache

innodb_flush_log_at_trx_commit 参数为1才会每次事务提交都调用fsync对redo log刷盘。
另外InnoDB存储引擎有一个后台线程,每隔1s就会把redo log buffer中的内容写到系统文件缓存(page cache),然后调用fsync刷盘。

每秒自动刷盘

除了定时刷盘,设置的事务提交刷盘,还有一种情况:redo log buffer占用的空间达到innodb_log_buffer_size一半的时候,后台线程会主动刷盘。
注意刷盘策略为1时不会有数据丢失。
刷盘策略为0时,mySQL挂了会丢失一秒数据
刷盘策略为2时,MySQL挂了不会丢失数据,宕机会有1秒数据丢失。

日志文件组

硬盘上存储的redo log日志文件不止一个,而是以一个日志文件组的形式出现的。每个redo日志文件大小都是一样的。
比如可以配置为一组4个文件,每个文件的大小都是1G,整个redo log日志文件组可以记录4G内容。
它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写。如下图:


image.png

在日志文件组中还有两个重要的属性,分别是write pos,checkpoint

  • write pos是当前记录的位置,一边写一边后移
  • checkpoint是当前要擦除的位置,也是往后移

每次刷盘redo log记录到日志文件组中,write pos位置就会后移更新
每次MySQL加载日志文件组恢复数据时,会清空加载过的redo log记录,并把checkpoint后移更新。
write pos和checkpoint之间还空着的部分可以用来写入写的redo log记录。
如果write pos追上了checkpoint,说明日志文件组满了,这时候不能写入新的redo log记录,MySQL得清空一些记录,把checkpoint推进一下。

redo log小结

只要每次把修改后的数据页直接刷盘就行了,为什么还要用redo log?
实际上数据页大小是16kb,刷盘比较耗时间,可能就修改了几byte的数据,没必要把完整的数据页刷盘。
而且数据页刷盘是随机写,因为一个数据页对应的位置可能在硬盘文件的随机位置,所以性能很差。
如果是写redo log,一行记录可能就几十byte,只包含空间号,数据页号,磁盘文件偏移量,更新值,加上是顺序写,所以刷盘速度很快。
所以用redo log的形式记录修改内容,性能远远超过刷数据页的方式。

binlog

redo log是物理日志,记录内容是在某个数据页上做了什么修改。属于InnoDB存储引擎。
而binlog是逻辑日志,记录内容是语句的原始逻辑,类似于给id是2是这行c字段+1.属于mysql server层。
不管用什么存储引擎,只要发生了表数据更新,都会产生binlog日志。
binlog可以说是MySQL数据的数据备份,主备,主主,主从都离不开的。需要依靠binlog来同步数据,保证数据一致性。

binlog日志用法

binlog会记录所有涉及更新数据的逻辑操作,并且是顺序写。

记录格式

binlog日志有三种格式,可以通过binlog_format参数指定。

  • statement
  • row
  • mixed

指定statement,记录的内容是sql语句原文。同步数据时,也会执行记录的sql语句。但是问题是如果有采用系统当前时间的sql,会导致时间与之前不一致。
row记录的内容不是简单的sql语句了,还包括操作的具体数据。row格式记录的内容看不到详细信息,需要通过mysqlbinlog工具解析出来。
这样能保证同步数据的一致性,通常情况下也都是指定为给row的,这样可以为数据库的恢复和同步带来更好的可靠性。
但是这种方式需要大量的容量来记录,比较占用空间,恢复和同步时会消耗更多的IO资源,影响执行速度。
所以mixed是折中方案,是MySQL如果判断这条sql可能引起数据不一致会使用row格式,否则用statement格式。

写入机制

binlog的写入机制也非常简单,事务执行过程中,先把日志写到binlog cache中,事务提交的时候,再把binlog cache写到binlog文件中。
因为一个事务的binlog不能被拆开,无论这个事务多大也要一次性写入。所以系统会给每个线程分配一块内存作为binlog cache。
我们可以通过binlog_cache_size参数控制单个线程binlog cache大小,如果存储内容超过了这个参数要暂存到磁盘中。


binlog 日志刷盘流程

上图的write是指日志写入到文件系统的page cache,并没有把数据持久化,所以比较快
fsync才是将数据持久化到磁盘的操作

write和fsync的时机,可以由参数sync_binlog控制,默认是0.

  • 设置为0:每次事务提交都write,由系统判断什么时候fsync。虽然性能提升,但是机器宕机会丢失部分数据。
  • 设置为1:每次提交都执行fsync
  • 设置为n:每次提交都write,累积n个事务才fsync。

在出现IO瓶颈的场景里,将sync_binlog设置成一个比较大的值,可以提升性能。代价是机器宕机丢失最近N个事务的binlog日志。

两阶段提交

redo log(重做日志)让InnoDB存储引擎有了崩溃恢复的能力
binlog(归档日志)保证了MySQL集群架构的数据一致性

虽然他们都属于持久化的保证,但是侧重点不同。而且两者写入时机也不同。redo log会记录每一条sql语句,而binlog只会记录提交了事务的sql。
为了解决两份日志之间的逻辑一致问题,InnoDB存储引擎使用两阶段提交方案。
原理很简单,就是将redo log的写入拆成两个步骤:prepare和commit。这就是两阶段提交。


两阶段提交

在使用两阶段提交后,写入binlog发生异常也不会有影响。因为redo log日志恢复时,发现redo log还处于prepare阶段,并且没有对应的binlog日志,就会回滚事务。
不过哪怕redo log处于pepare阶段,但是在binlog能通过事务id找到对应日志,就不会回滚了。

undo log(回滚日志)

我们知道如果想要保证事务的原子性,就要在异常发生时对已经执行的操作进行回滚。在MySQL中,恢复机制是通过回滚日志实现的。所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常,我们直接利用回滚日志中的信息将数据回滚到修改之前的样子。
并且回滚日志会先于数据持久化到磁盘上。这样就保证了哪怕数据库宕机,也能正常回滚。
另外MVCC的实现依赖于:隐藏字段,Read View,undo log。在内部实现中,通过数据行的db_trx_id和Read View来判断数据的可见性,如果不可见则会找历史版本,每个事务 读取到的版本可能是不一样的。在同一个事务中,用户只能看到该事务创建Read View之前已经提交的修改和该事务本身做的修改。

总结

MySQL InnoDB引擎使用了redo log(重做日志)保证了事务的持久性,使用undu log(回滚日志)保障事务的原子性。而数据库的数据备份,主备,主主,主从都离不开binlog。需要依靠binlog来同步数据,保证数据的一致性。

本篇笔记就记到这里,如果稍微帮到你了记得点个喜欢点个关注。我是认为这种基础知识还是挺有用的,而且很多思想和方案都很值得借鉴。也祝大家工作顺顺利利吧!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容