binlog 写入机制及高并发写入事务性能优化

binlog 和 redo log,前者负责数据库数据的全量备份和恢复,可以在主从之间保证数据一致性,后者负责数据库事务更新数据的备份和恢复,可以在数据库异常崩溃重启后将已提交事务未持久化到磁盘的数据更新恢复,两者相辅相成,共同拱卫 MySQL 数据库数据的持久性和一致性。

关于 redo log 的底层写入机制,我们已经在数据库事务中详细介绍过,今天这篇教程,我们主要来看看 binlog 的底层写入机制,以及如何优化数据库写入事务性能。

注:我们知道,redo log 是重做日志,所以起名 redo,那 binlog 是啥含义呢?其实早期版本的 MySQL 只维护了 binlog,它会将所有 DDL 和 DML 语句以 Event 形式记录到一个二进制日志(binary log)中,这个 binary log 就被简称为 binlog。

binlog 底层写入机制

既然涉及到 redo log,那对应的底层存储引擎肯定就是 InnoDB 了,无论是对事务支持,还是并发性能(锁机制)上,InnoDB 都是相对于 MyISAM 引擎更好的选择,所以目前主流的 MySQL 数据库存储引擎都会选择 InnoDB,除非你的数据库主要就是读操作。所以接下来,我们依然基于 InnoDB 引擎来介绍 binlog 写入机制。

和 redo log 一样,binlog 也只关心数据库更新操作(插入、删除、更新),查询操作不对对数据库有更改,所以记录下来也没有意义。

binlog 的写入逻辑要比 redo log 简单许多,和所有数据库数据和日志更新操作一样,为了性能考虑,binlog 也不会直接写入磁盘,MySQL 会为每个线程分配独立的 binlog cache(内存块,类似 redo log buffer,分配时机是在事务开启后第一次执行 DDL/DML 语句,然后将所有更新操作先记录到 binlog cache。

这个 binlog cache 大小是有上限的,可以通过 binlog_cache_size 配置项调节,默认是 32 KB:

如果超过这个限制,会将 binlog cache 中的缓存日志刷新到存储在磁盘里的 binlog 临时文件(redo log buffer 则是在超过容量一半时直接刷新到 redo log),同时清空 binlog cache,这个临时文件的大小则可以通过 max_binlog_cache_size 配置项配置:

其默认值是很大的,一般来说不会超过这个限制,如果超过了,系统会报错。

事务提交后会将 binlog cache 和 binlog 临时文件的所有日志持久化到磁盘里的 binlog 二进制文件,也就存储 MySQL 数据的目录下:

其中 binlog.00000* 存储的是具体的日志信息,binlog.index 记录的是所有 binlog 文件的索引。你也可以在 MySQL 中通过 show binary logs 命令查看所有的 binlog 日志:

之后会清空对应的 binlog cache 和 binlog 临时文件,至此就完成了一个事务的 binlog 日志写入操作。

需要注意的是每个事务线程都有自己的 binlog cache 和 binlog 临时文件,但是会共用同一个 binlog 文件。

优化高并发写入事务性能
sync_binlog
如果更细致的划分的话,真正持久化到磁盘 binlog 日志也是分两步进行的,首先会将日志持久化达到操作系统的文件系统页面缓存(FS Page Cache),然后再根据一定的策略真正写入 binlog 磁盘文件,这个策略可以通过 sync_binlog 配置项来设置:

  • sync_binlog=0:表示每次提交事务都写入到文件系统页面缓存,不持久化到 binlog 磁盘文件;
  • sync_binlog=1:表示每次提交事务都会立即写入 binlog 磁盘文件;
  • sync_binlog=N(N>1):表示每次提交事务都写入到文件系统页面缓存,累积到 N 个事务后才持久化到 binlog 磁盘文件。

这样做的原因当然是为了性能考虑,写入到文件系统页面缓存相较于持久化到磁盘的系统开销更小,可以忽略不计,但是也有风险,就是服务器崩溃重启后文件系统页面缓存就不存在了,但是如果只是服务器中的 MySQL 进程崩溃重启,则页面缓存中的数据依然有效,所以在高并发场景下,上述 sync_binlog 可以设置为一个大于 N 的值,比如 100-1000,其风险是服务器崩溃重启后(概率很低),其中累积的 binlog 日志会丢失。

该配置项的默认值是 1,表示每次提交事务会立即持久化到 binlog 磁盘文件:

innodb_flush_log_at_trx_commit
redo log 也有类似的机制。

我们之前介绍 redo log 时提到 redo log buffer 会在事务提交时持久化到 redo log,这是通过 innodb_flush_log_at_trx_commit 配置项默认值是 1 来控制的:

其实这个配置项还支持其他配置值:

  • 0:表示每次事务提交时不将 redo log buffer 中的日志持久化到磁盘;
  • 1:表示每次事务提交时都将 redo log buffer 中的日志持久化到 redo log 磁盘文件;
  • 2:表示每次事务提交时都将 redo log buffer 中的日志写入到文件系统页面缓存。

InnoDB 后台进程每隔 1s 将 redo log buffer 日志刷新到 redo log 时底层就是借助了页面缓存作为中介,并不是直接持久化到 redo log 磁盘文件的。同理 innodb_flush_log_at_trx_commit 配置为 2 的时候,也存在服务器重启后累积的日志数据丢失的风险。

我们再回顾下 redo log 的两阶段提交:

如果 innodb_flush_log_at_trx_commit 配置值为 1 的话,其实在 redo log prepare 阶段就会持久化 redo 日志到磁盘文件。

优化写入事务性能
我们知道在数据库写入操作时真正涉及磁盘操作的也就是这里的两个日志写入了,更新的数据页是在内存 Buffer Pool 中完成的,所以降低了这两个日志的磁盘 IO 也就等同于优化了写入性能。

因此,我们可以通过将上面介绍的 sync_binlog 配置为 N(N > 1),innodb_flush_log_at_trx_commit 配置为 2 调整日志真正写入磁盘文件的时机来优化高并发写入事务的性能:

这样一来,我们就可以实现 binlog 和 redo log 的组提交,尽可能减少磁盘 IO,这里存在的潜在风险是第 3 步之前服务器崩溃重启后页面缓存中累积的重做日志和 binlog 日志会丢失,不能恢复这期间的更新数据,但是 MySQL 异常崩溃重启后可以不受影响。实际情况下,除了机房断电等不可控因素,基本不会出现服务器异常崩溃重启的情况。

有人可能会疑惑这里的日志写入涉及到磁盘操作,会不会影响 MySQL 性能,其实很小,因为 redo log 和 binlog 记录的信息量很小,而且都是追加写入,属于顺序 IO,只有随机 IO 是最耗性能的,比如对数据表进行更新操作就是典型的随机 IO,因为每次都要去不同的位置进行操作。这里我们将日志先写入页面缓存,再同步到磁盘文件,也会极大降低日志写入的磁盘 IO。

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

推荐阅读更多精彩内容