mysql的页断裂(partial write)问题与(double write)技术

1. 页断裂

1.1 什么叫做页断裂(partial write)

页断裂是数据库宕机时,数据库页面只有部分写入磁盘,导致页面出现不一致的情况。

1.2 为什么会发生页断裂

InnoDB中有记录(Row)被更新时,先将其在Buffer Pool中的page更新,并将这次更新记录到Redo Log file中,这时候Buffer Pool中的该page就是被标记为Dirty(脏页)。在适当的时候(Buffer Pool不够、Redo不够,系统闲置等),这些Dirty Page会被Checkpoint刷新到磁盘进行持久化操作。

mysql的一个update需要经历什么最终持久化到磁盘?

我们知道,InnoDB的Page Size是16KB,其数据校验也是针对这16KB来计算的,将数据写入到磁盘是以Page为单位进行操作的。我们知道文件系统是以4k为单位写入,机械磁盘是以扇区(512字节)为单位写入(SSD本质上虽然没有扇区概念,但为了兼容机械盘,也搞出了这么一个512字节扇区这么一个写方式),不能保证MySQL数据页面16KB的一次性原子写。试想,在某个Dirty Page flush的过程中,发生了系统断电(或者OS崩溃),16K的数据只有8K被写到磁盘上,只有一部分写是成功的,这种现象被称为(partial page writes、torn pages、fractured writes)。

查看innoDB的Page Size大小

mysql> show variables like 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.00 sec)

查看OS block Size大小

$ getconf PAGESIZE

4096

1.3 InnoDB使用redo log可以恢复页断裂吗

一旦partial page writes发生,那么在InnoDB恢复时就很尴尬:redo log的页大小一般设计为512个字节,因此redo log page本身不会发生break page。用redo log来解决partial write 理论上是可行的,不过innodb的redo log是物理逻辑日志,并不是纯物理日志,因此发生partial write后崩溃恢复过程中不能直接应用redo log ,innodb发现break page后实际上会报错。

注:mysql的逻辑日志、物理日志与物理逻辑日志

物理逻辑日志不是完全幂等的,这取决于重做日志类型,对于INSERT产生的日志其不是幂等的。

2. double write

2.1 简述

为了解决页断裂(partial write)问题,InnoDB实现了double write机制。

简单来说,在写数据页之前,先把这个数据页写到一个独立的物理文件位置(ibdata),然后再写到数据页。这样在宕机恢复的时候,如果数据页损坏,那么在应用redo log之前,需要通过该页的副本来还原该页,然后在进行redo log重做。这就是doublewrite。doublewrite技术带给innodb存储引擎的是数据页的可靠性。

2.2 double write体系结构和工作流程

double write由两部分组成,一部分是InnoDB内存中的double write buffer,大小为2MB,另一部分是物理磁盘上的ibdata,系统表空间中大小为2MB,共128个连续的Page(2*1024/16KB=128),即两个分区(extend)一个段(segment)。其中120个页用于批量刷新脏页(如LRU LIST刷新与FLUSH LIST刷新这两种刷新策略),另外8个页用于单页刷新(Single Page Flush)。做区分的原因是批量刷脏是后台线程做的,不影响前台线程。而单页刷新是用户线程发起的,需要尽快的刷脏页并替换出一个空闲页出来。

InnoDB刷新(写出)缓冲区中的数据页时采用的是一次写多个页的方式:

  1. 多个页就可以先顺序写入到double write buffer,并调用fsync()保证这些数据被刷新到double write磁盘(ibdata)。
  2. 然后数据页调用fsync()被刷新到实际存储位置;
  3. 故障恢复时InnoDB检查double write Buffer与数据页原存储位置的内容,若double write页处于页断裂状态,则简单的丢弃;若数据页不一致,则从double write页还原。
double write 流程.png

由于double write页落盘与数据页落盘在不同的时间点,不会出现double write页和数据页同时发生断裂的情况,因此doublewrite技术可以解决页断裂问题,进而保证了重做日志能顺利进行,数据库能恢复到一致的状态。

2.3 double write性能损耗

表面看上去,每个页面都写了2遍,会非常影响性能。但实际上,由于所写的页面会先缓存到内存中,因此每一部分缓存空间在满了之后才会真正的写入文件。并且double write是一个连续的存储空间,所以硬盘在写数据的时候是顺序写,而不是随机写,这样性能很高。doublewrite有效利用这个特点,所以降低并不会相差1倍,经过测试,大概5-10%左右。当然,这是针对普通磁盘。对于目前比较流行的SSD来说,随机写已经不是问题,性能影响可能更小。

2.4 double write的配置

double write并不是什么特性或优点,它只是一个被动解决方案而已。这个问题的本质就是磁盘在写入时,都是以512字节为单位,不能保证MySQL数据页面16KB的一次性原子写,所以才有可能产生页面断裂的问题。而目前有些厂商从硬件驱动层面做了优化,可以保证16KB(或其他配置)数据的原子性写入。如果真是这样,那么两次写就完全没有必要了,取消两次写,才是最终级优化。

mysql的double write默认开启,参数skip_innodb_doublewrite虽然可以禁止使用doublewrite功能,但还是强烈建议大家使用doublewrite,避免部分写失效问题。

mysql> show variables like '%double%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+
1 row in set (0.00 sec)

2.5 InnoDB能否通过其他方式解决partial write

其实保证mysql数据页面(16KB)原子性的写入到磁盘(每次512字节)中,就可以解决partial write。

  1. 如果系统表空间文件(“ibdata文件”)位于支持原子写入的Fusion-io设备上,就能避免partial write ;
  2. 阿里云polardb,在底层分布式文件系统PolarFS能提供页大小(如16)KB小的原子写入,无需double write机制来避免partial write。

推荐阅读

MySQL InnoDB特性:两次写(DoubleWrite)

页断裂(partial write)与doublewrite技术

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

推荐阅读更多精彩内容