15 - 日志的相关问题

关键字

日志、索引

这一章是专栏老师的答疑课,在这一节中,主要解决了一些关于日志和索引的疑惑。

日志相关问题

在第二篇文章中,讲到了 binlog 和 redo log,这两个日志使用了两阶段提交。这样的方法可以解决崩溃恢复的问题。在这里,就详细分析一下在 MySQL 发生异常重启的时候,是怎么保证数据完整性的。

首先看一下在第二篇文章中的图:
15-崩溃恢复.jpg

在这里,我们就分析一下,在两阶段提交的不同时刻,MySQL 异常重启会出现什么现象。

  • 如果在 时刻A 发生重启,也就是 redo log 处于 prepare 阶段之后、写 binlog 之前发生了崩溃。此时,由于 binlog 还没写,redo log 没提交,所以在恢复的时候,这个事务会回滚。

  • 如果 时刻B 发生重启,也就是在 binlog 写完,redo log 还没有 commit 时发生了崩溃。此时有两个判断规则:
    1.如果 redo log 里的事务完整,即已经有了 commit,则直接提交。
    2.如果 redo log 的事务只有 prepare,则需要判断 binlog 是否存在且完整。如果完整,提交事务;如果不完整,回滚。

在 时刻B,已经有了完整的 binlog,崩溃恢复的事务会被提交。

追问:MySQL 怎么知道 binlog 是否完整?

答:一个事务的 binlog 是有完整格式的,所以,MySQL 有办法验证事务 binlog 的完整性。

追问:redo log 和 binlog 是如何关联起来的?

答:它们有一个共同的字段,XID。崩溃恢复的时候,会顺序扫描 redo log:

  • 如果 redo log 中既有 prepare 又有 commit ,就直接提交。
  • 如果只有 prepare,而没有 commit,则需要拿着 redo log 中的 XID 去 binlog 中寻找对应事务。
追问:prepare 的 redo log + 完整的 binlog --> 重启后提交这个事务。为什么不设置为回滚?

答:在 时刻B,binlog 已经写入了,之后就会被从库(或用这个 binlog 恢复出来的库)使用。所以,在主库也要提交这个事务,以保持主库和备库的数据一致性。

追问:为什么要这样设计两阶段提交呢?为什么不先写完 redo log,再写 binlog。崩溃恢复的时候,要求两个日志都完整才可以回复。是不是也是一样的逻辑?

答:不是的,对于 InnoDB 引擎来说,如果 redo log 提交完成了,事务就不能回滚(如果这还允许回滚,就可能覆盖掉别的事务的更新)。而如果 redo log 直接提交,然后 binlog 写入的时候失败,InnoDB 又回滚不了,数据和 binlog 日志又不一致了。

所以,只有当每个人都说“我 OK ”的时候,再一起提交。

追问:为什么不能用 binlog 既支持崩溃回复,又支持归档呢?

注:言下之意是:只保留 binlog,然后可以把提交流程改成这样:… -> “数据更新到内存” -> “写 binlog” -> “提交事务”,是不是也可以提供崩溃恢复的能力?

答:不可以。这有历史原因实现上的原因两个方面。

历史原因:InnoDB 并不是 MySQL 的原生引擎。MySQL 的原生 MyISAM 引擎并不支持崩溃恢复。

InnoDB 作为插件加入 InnoDB 之后,才通过 redo log 提供了崩溃回复的功能。

实现上的原因:在下面的图中,没有 redo log,如果在指定的地方发生崩溃,会出现一些问题:

15-只有binlog.jpg

在发生 crash 时,binlog2 写完了,但是 事务2 还没有 commit。

重启后,事务2 会进行回滚,然后使用 binlog2 补回来;但是对于 事务1 来说,因为已经 commit,所以并不会使用 binlog1。

InnoDB 使用的是 WAL,执行事务的时候,写完内存和日志,事务就算完成了,注意,此时内存中的数据并不一定已经刷到了磁盘中

所以,如果在图中的位置发生崩溃,事务1 可能会丢失,而且是数据页级别的丢失。所以,目前来说,binlog 还不能支持崩溃恢复。

追问:能不能只用 redo log,不用 binlog?

答:如果只从崩溃恢复的角度来讲是可以的。关掉 binlog 之后系统依然是 crash-safe 的。

但是,binlog 拥有很多其它功能,比如归档、比如在异构系统中消费 binlog 来更新自己的数据。如果关掉 binlog,这些功能都无法使用。

总之,很多系统机制都依赖 binlog,所以从生态的角度来看,binlog 必不可少。

追问:redo log 设置多大?

答:如果 redo log 设置太小,会很快被写满,然后触发强行刷 redo log,这会降低性能。

所以,如果你的磁盘足够,就不要太小气了,直接将 redo log 设置为 4 个文件、每个文件 1GB 吧。

追问:数据的最终落盘,是从 redo log 更新还是从 buffer pool 更新呢?

答:实际上,redo log 并没有记录数据页的完整数据,所以最终落盘,不可能是由 redo log 更新过去的。

  • 脏页落盘和 redo log 毫无关系。
  • 在崩溃恢复中,InnoDB 如果判断一个数据页可能丢失更新,就会将它读到内存中,然后用 redo log 更新内存内容。更新后,就又变成了脏页落盘的问题,这就和 redo log 无关了。

小结

这是一篇答疑文章,主要回答了日志的相关问题。实际上,专栏文章还讲到了一个比较复杂的问题,但是我并没有理解那个问题,所以在这里就没有写出。如果对之后的问题感兴趣,可以到专栏中找一找。

上期问题

上期的问题是,用一个计数表记录一个业务表的总行数,在往业务表插入数据的时候,需要给计数值加 1。

逻辑实现上是启动一个事务,执行两个语句:

  • insert into 数据表;
  • update 计数表,计数值加 1。

从系统并发能力的角度考虑,怎么安排这两个语句的顺序。

解答:

并发系统性能的角度考虑,应该先插入操作记录,再更新计数表。
知识点在《行锁功过:怎么减少行锁对性能的影响?》
因为更新计数表涉及到行锁的竞争,先插入再更新能最大程度地减少事务之间的锁等待,提升并发度。

本期思考

我们创建了一个简单的表 t,并插入一行,然后对这一行做修改。

mysql> CREATE TABLE `t` (
`id` int(11) NOT NULL primary key auto_increment,
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB;
insert into t values(1,2);

这时候,表 t 里有唯一的一行数据 (1,2)。假设,我现在要执行:

mysql> update t set a=2 where id=1;

你会看到这样的结果:
15-课后思考.png

结果显示,匹配 (rows matched) 了一行,修改 (Changed) 了 0 行。

仅从现象上看,MySQL 内部在处理这个命令的时候,可以有以下三种选择:

  1. 更新都是先读后写的,MySQL 读出数据,发现 a 的值本来就是 2,不更新,直接返回,执行结束;
  2. MySQL 调用了 InnoDB 引擎提供的“修改为 (1,2)”这个接口,但是引擎发现值与原来相同,不更新,直接返回;
  3. InnoDB 认真执行了“把这个值修改成 (1,2)"这个操作,该加锁的加锁,该更新的更新。

你觉得实际情况会是以上哪种呢?你可否用构造实验的方式,来证明你的结论?进一步地,可以思考一下,MySQL 为什么要选择这种策略呢?


以上就是本节内容,愿你能解决疑问。

注:本文章的主要内容来自我对极客时间app的《MySQL实战45讲》专栏的总结,我使用了大量的原文、代码和截图,如果想要了解具体内容,可以前往极客时间

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