MySQL中的double write(二)(r12笔记第17天)

    MySQL里的double write是InnoDB的三大闪亮特性,另外两个是insert buffer
和自适应哈希,其实还有几个比如异步IO,Flush neighbour
Page(刷新邻接页),这个和系统层面的关联性较高,所以三大亮点还是更有针对性的。

   当然一说到MySQL里的double write,其实主要是要应对一个很自然的问题,那就是partial write。

经典的partial write问题

  
这个问题比较经典,很多数据库设计中都需要考虑到这样一个临界点的问题,MySQL中的页是16k,数据的校验是按照这个为单位进行的,而操作系统层面的数据单位肯定达不到16k,比如是4k,那么一旦发生断电的时候,只保留了部分写入,如果是Oracle
DBA一般对此都会很淡定,说用redo来恢复嘛,但是可能我们被屏蔽了一些细节,MySQL在恢复的过程中一个基准是检查page的checksum,也就是page的最后事务号,发生这种partial
page write 的问题时,因为page已经损坏,所以就无法定位到page中的事务号,所以这个时候redo就无法直接恢复。

   由此引申一点,partial write的问题在Oracle中肯定也会存在,但是只是Oracle替我们把这个过程平滑的做好了。其中有设计的差异,还有恢复技术的差别。但是无论如何这个问题都不会绕过去,还得解决。

   所以这一类问题,如果讨论起来,那可以讨论很长时间,可以把体系结构里的方方面面拿出来分析,做对比。

简单分析double write问题

   对此我画了一个相对简陋的图,也欢迎大家提出改进建议。

   
总体来说,double write
buffer就是一种缓冲缓存技术,主要的设计就是为了防止数据在断电,异常情况下丢失数据。里面有几个点需要注意的就是,数据在buffer
pool中修改后成了脏页,这个过程会产生binglog记录和redo记录,当然数据写入数据文件是一个异步的工作,如果细看,在共享表空间(system
tablespace)中会存在一个2M的空间,分为2个单元,一共128个页,其中120个用于批量刷脏数据,另外8个用于Single Page
Flush。根据阿里同学的分析主要是做区分是因为批量刷脏是后台线程做的,这样不影响前台线程。而Single page
flush是用户线程发起的,需要尽快的刷脏并替换出一个空闲页出来。所以不是一个严格的64+64的拆分。

      
而数据刷新的过程,是先使用memcopy把脏数据复制到内存中的double write
buffer,分两次写完,每次写1MB到共享表空间,然后就是调用fsync来同步到磁盘。这里有一点需要注意的是,这个刷新到共享表空间的过程,虽然是两次,但是是顺序写,所以开销不会很大,也就不会像大家想象的double
write性能可能很差,根据Percona的测试,大概也就是5%左右的差别,数据重要还是性能更重要,这是一个基本的命题。当然后续会再写入对应的表空间文件中,这个过程就是随机写,性能开销就会大一些。所以在早些时候是用SSD的时候很多人也会带有如此的顾虑,顺序写还是随机写。

    当然double write这么设计就是全面为了作为恢复而用,要不这么大张旗鼓就不值得了。这个图来源于 http://blog.csdn.net/renfengjun/article/details/41541809

  我觉得已经说得很明白了,就直接引用过来了。

  
可以看到里面的一个中心词就是checksum,如果出现了partil
write的时候,比如断电,那么两次写的过程中,很可能page是不一致的,这样checksum校验就很可能出现问题,而出现问题的时候,因为有了前期写入共享表空间的页信息,所以就可以重构出页的信息重新写入。

double write的另外一个作用

    double write其实还有一个特点,就是将数据从double write buffer写到真正的segment中的时候, 系统会自动合并连接空间刷新的方式, 这样一来每次就可以刷新多个pages,提高效率。

比如下面的环境,我们可以根据show status的结果来得到一个基本的合并页的情况。

> show status like '%dbl%';  
+----------------------------+----------+
| Variable_name              | Value    |
+----------------------------+----------+
| Innodb_dblwr_pages_written | 23196544 |
| Innodb_dblwr_writes        | 4639373  |
+----------------------------+----------+通过InnoDB_dblwr_pages_written/InnoDB_dblwr_writes  就可以得到,通过指标也可基本看明白。
   

Percona中的double write改进

 

   当然对于double write,在Percona中也在持续改进,在Percona 5.7版本中做了一个改进,你可以看到一个新的参数,innodb_parallel_doublewrite_path

| innodb_parallel_doublewrite_path | xb_doublewrite |在系统层面,也会存在一个30的一个文件对应。

-rw-r----- 1 mysql mysql 31457280 Mar 28 17:54 xb_doublewrite也就是并行double
write,关于这个特性的详细描述和测试,可以参考。https://www.percona.com/blog/2016/05/09/percona-server-5-7-parallel-doublewrite/?utm_source=tuicool&utm_medium=referral

里面提供了很多详细测试的对比和分析。当然MariaDB,Facebook,Aurora也有一些自己的实现方式和考虑,这个限于精力,还没有细细测试分析。感兴趣的同学可以看一看。

参考链接:

http://blog.itpub.net/22664653/viewspace-1140915/

时间: 2024-07-30 05:42:21

MySQL中的double write(二)(r12笔记第17天)的相关文章

从MySQL中的double write问题说开去

有句话说得好,世上只有两种工具,一种是被人骂的,另一种是没人用的.被骂得越多,侧面反映出关注度越高,使用率越高,越用越成熟,这一点上, MySQL就是一个很不错的例子.而MySQL可支持的存储引擎很多,目前以InnoDB最佳,算为上品.   自MySQL 5.5.5开始,InnoDB是作为默认的存储引擎,而之前MyISAM存储引擎其实也占有一席之地,但MySQL开发团队自宣布MySQL 8.0.0开发里程碑版本DMR开始,就把MySQL版本一下子从5.x跳跃到了8.0.其中的一个亮点就是事务性数

MySQL中的基本查询语句学习笔记_Mysql

1.基本查询语句select 属性列表 from 表名和视图列表 [where 条件表达式1] [group by 属性名1 [having 条件表达式2]] [order by 属性名2 [asc|desc]]2.单表查询1)使用*查询所有字段 select * from 表名: 2) 查询指定字段 select id,name from product: 使用上面例子可以查询指定字段 3)查询指定记录 where 条件表达式 实例: select *from employee where i

浅谈MySQL中的事务隔离级别(r11笔记第86天)

   之前写了一篇浅谈事务(一),算是对事务的一个基本认识,今天来简单总结一下事务的隔离级别,虽然是老掉牙的知识点,重温一下还是值得的.    在MySQL中基本有这两种事务隔离级别的设置,默认的RR(Repeatable-Read)和实际中常见的RC(Read-Committed).两者区别是什么,怎么正确理解,用几个SQL语句就能说明白,就用简单的实验来说明白.    我们开始吧.        首先创建一个测试表test,插入一些数据. create table test( id int

MySQL数值类型在binlog中需要注意的细节(r12笔记第69天)

    MySQL里的数值类型分得很细,光整型数据就有多种数据类型.tinyint,smallint,mediumint,int(integer),还有范围最大的bigint,它们对应的数值范围也大大不同,大体来说就是下面的数值范围,从有符号数和无符号数来区别对待. 类型名称 有符号数(signed) 无符号数(Unsigned) tinyint -129~127 0~255 smallint -32768~32767 0~65535 mediumint -8388608~8388607 0~1

Oracle中的PGA监控报警分析二(r12笔记第87天)

今天又收到了一条报警的信息,看起来很常规,但是后面的故事如果你做了分析就会发现其实本身并不平常,我觉得我得出手了. ZABBIX-监控系统: ------------------------------------报警内容: PGA Alarm on alltest ------------------------------------报警级别: PROBLEM ------------------------------------监控项目: PGA:9723.2 -------------

MySQL service启动脚本浅析(r12笔记第59天)

我们在搭建MySQL环境的时候,一般都会按照建议的标准规范来做,比如拷贝mysql.server到自启动目录下. cp -rf $basedir/support-files/mysql.server /etc/init.d/mysql 然后设置MySQL自启动的服务,配置完成之后就可以运行命令service mysql.server start 来启动MySQL了. /sbin/chkconfig --add mysql /sbin/chkconfig --level 2345 mysql on

MySQL中的半同步复制(r11笔记第65天)

关于MySQL的复制架构,大体有下面三种方式,异步,全同步复制,半同步复制. 三种复制方式     第一种是异步复制,是比较经典的主从复制,搭建主从默认的架构方式,就是属于异步的,相对来说性能要好一些.但是还是会有丢失数据的情况.     第二种是全复制,比如说MySQL Cluster这样的方式,是属于全复制的,实际上MySQL Cluster其实发展并不大顺利,更多时候是一个实验室产品,但是时间定格在2016年12月12日,MySQL  5.7.17 GA的重大特性group replica

分分钟搭建MySQL一主多从环境(r12笔记第31天)

   之前写过一篇分分钟搭建MySQL Group Replication的测试环境,如果我们在一台服务器上想搭建一主多从的测试环境,怎么能够分分钟搞定呢,其实稍花点时间写个脚本即可搞定,无非就是把哪些程式化的东西整合起来,化繁为简.能够提高效率才是好.    搭建主从的环境,我们还是准备一个配置文件init2.lst,里面主要是端口和节点标示. 24801 s1   Y 24802 s2   N 24803 s3   N 24804 s4   N 24805 s5   N比如上面的写法,就是我

MySQL中GTID和自增列的数据测试(r12笔记第38天)

  昨天的一篇文章,今天有不少网友向我确认一些细节,我想最近正好在看GTID的东西,可以揉在一起来说说.    GTID这个概念看似简单,实际上还是有不少的门道. 我们来从架构的设计角度来看看存在哪些场景需要考虑GTID的变化.   一主两从的架构模式下GTID的变化   我们就以一主两从的架构为基准进行阐述.在这个架构模式下我们会用到MHA的方案.    如果这个时候Master节点宕机了,MHA就会开启检查机制. 这个时候Slave 1节点就会变为新的Master,Slave 2会从Slav