什么是 "read-on-write" problem?

在我们使用最常见的buffer write 中 "read-on-write" 问题指的是当我需要进行小于4k 大小buffer write 的时候, 需要先将数据所在的page 从disk 中读取出放入到page cache, 在page cache 中修改好, 然后再将这4k 数据写入回去. 这样在buffer write 的时候就多了一次磁盘IO

InnoDB 的做法是, 判断这个4k page 是不是第一次写入, 如果是第一次写入的话, 那么我会将这次写入填0, 变成4k 大小的size, 然后进行写入, 这样就可以避免了一次 "read-on-write" 操作, 后续继续写入的时候, 就不需要进行4k 大小的io, 因为这个时候数据已经在page cache 中, 直接写入就可以的.

我原先的想法是在内存中保留这个4k 大小的buffer, 每次修改都修改4k 大小的buffer, 每次写入也都进行4k 大小的写入, 这样做法反而不过InnoDB 的做法来得好, 因为每次写入都变成4k, 从用户空间拷贝到page cache 也需要拷贝4k 大小的数据, 而InnoDB 的做法只需要拷贝数据大小的size 就可以, 做的更细

在这里的测试case 和InnoDB redo log 场景类似, 是循环使用文件的场景, 在LevelDB/RocksDB 的wal 中, 由于每次都是创建新文件并进行append写入, 就不需要读取原先page 的内容, 因此是并不存在这样的问题. 但是LevelDB/RocksDB 存在的另一个问题是Append write 性能比overwriting 会差很多. 下次再对比测试.

下面两个例子可以看出同样写1G 大小的文件. InnoDB 的做法比标准追加写入做法提高40%

http://t.cc

write time microsecond(us) 51668825

http://t2.cc

write time microsecond(us) 29358162

 // t.cc// 标准的通过pwrite 的写入方法// 如果将这里的pwrite 改成write, 我们获得的还是几乎一样的performance// num = pwrite(fd, aligned_buf, dsize, off);// 估计在pwrite 内部实现, 如果只有一个线程写入, 并且这个offset 并没有移动, 就不需要先进行seek, 再write 了​#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/time.h>#include <stdint.h>#include <random>​#include <linux/falloc.h>#include <sys/syscall.h>​uint64_t NowMicros() {struct timeval tv;gettimeofday(&tv, NULL);return static_cast<uint64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;}int main(){uint64_t st, ed;uint64_t file_size = 1LL * 1024LL * 1024LL * 1024LL;int fd = open("/disk11/tf", O_CREAT | O_RDWR, 0666);int ret;unsigned char *aligned_buf;int dsize = 512;ret = posix_memalign((void **)&aligned_buf, 4096, 4096 * 10);for (int i = 0; i < dsize; i++) {aligned_buf[i] = (int)random() % 128;}​lseek(fd, 0, SEEK_SET);st = NowMicros();int num;off_t off = 0;for (uint64_t i = 0; i < file_size / dsize; i++) {num = pwrite(fd, aligned_buf, dsize, off);off += 512;fsync(fd);if (num != dsize) {printf("write error num %dn", num);return -1;}}ed = NowMicros();printf("write time microsecond(us) %lldn", ed - st);​return 0;}

iostat 上, 可以看到nvme8n1有明显的磁盘read IO 存在

 // t2.cc// InnoDB 优化做法, 在遇到第一个4k 对齐地址的时候, 将当前这一次IO 对齐成4k, 空闲的部分filling zero. 从而避免了这一次需要将该page 从文件中读取到Page cache#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/time.h>#include <stdint.h>#include <random>#include <stdlib.h>#include <string.h>​#include <linux/falloc.h>#include <sys/syscall.h>​uint64_t NowMicros() {struct timeval tv;gettimeofday(&tv, NULL);return static_cast<uint64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;}int main(){uint64_t st, ed;uint64_t file_size = 1LL * 1024LL * 1024LL * 1024LL;int fd = open("/disk11/tf", O_CREAT | O_RDWR, 0666);int ret;unsigned char *aligned_buf;int dsize = 512;ret = posix_memalign((void **)&aligned_buf, 4096, 4096 * 10);for (int i = 0; i < dsize; i++) {aligned_buf[i] = (int)random() % 128;}​lseek(fd, 0, SEEK_SET);st = NowMicros();int num;off_t off = 0;for (uint64_t i = 0; i < file_size / dsize; i++) {if (i % 8 == 0) {memset(aligned_buf + 512, 0, 4096);num = pwrite(fd, aligned_buf, 4096, off);} else {num = pwrite(fd, aligned_buf, dsize, off);}off += 512;fsync(fd);if (num != dsize && num != 4096) {printf("write error num %dn", num);return -1;}}ed = NowMicros();printf("write time microsecond(us) %lldn", ed - st);​return 0;}

iostat 可以看到这个时刻nvme8n1是没有磁盘的read IO 存在的

通过 blktrace 可以看到每一个IO的过程, 可以看详细的看到在t2 中是有read IO 的存在, 并且可以看到 在t 中read IO : write IO = 1:8

这是通过blktrace 看到的 t2 的IO

 259,9    2      357     0.001166883     0  C  WS 75242264 + 8 [0]## 一个IO 的开始259,6    2      358     0.001173249 113640  A  WS 75242264 + 8 <- (259,9) 75240216259,9    2      359     0.001173558 113640  Q  WS 75242264 + 8 [a.out]259,9    2      360     0.001173664 113640  G  WS 75242264 + 8 [a.out]259,9    2      361     0.001173939 113640  U   N [a.out] 1259,9    2      362     0.001174017 113640  I  WS 75242264 + 8 [a.out]259,9    2      363     0.001174249 113640  D  WS 75242264 + 8 [a.out]259,9    2      364     0.001180838     0  C  WS 75242264 + 8 [0]## 一个IO 的结束259,6    2      365     0.001187163 113640  A  WS 75242264 + 8 <- (259,9) 75240216259,9    2      366     0.001187367 113640  Q  WS 75242264 + 8 [a.out]259,9    2      367     0.001187477 113640  G  WS 75242264 + 8 [a.out]259,9    2      368     0.001187755 113640  U   N [a.out] 1259,9    2      369     0.001187835 113640  I  WS 75242264 + 8 [a.out]259,9    2      370     0.001188072 113640  D  WS 75242264 + 8 [a.out]259,9    2      371     0.001194495     0  C  WS 75242264 + 8 [0]259,6    2      372     0.001200968 113640  A  WS 75242264 + 8 <- (259,9) 75240216259,9    2      373     0.001201164 113640  Q  WS 75242264 + 8 [a.out]259,9    2      374     0.001201268 113640  G  WS 75242264 + 8 [a.out]259,9    2      375     0.001201540 113640  U   N [a.out] 1

从上面可以看出, 这个IO 从开始到结束都不会有Read 相关的IO

对比于t 产生的IO 是这样的

 # 一个IO 的开始, 从这里可以看到这里有读IO 的出现, 并且其实这里是每产生1个读IO, 后续跟着8个 write IO​259,6    0      184     0.001777196 58995  A   R 55314456 + 8 <- (259,9) 55312408259,9    0      185     0.001777463 58995  Q   R 55314456 + 8 [a.out]259,9    0      186     0.001777594 58995  G   R 55314456 + 8 [a.out]259,9    0      187     0.001777863 58995  D  RS 55314456 + 8 [a.out]259,9    0      188     0.002418822     0  C  RS 55314456 + 8 [0]# 一个读IO 结束259,6    0      189     0.002423915 58995  A  WS 55314456 + 8 <- (259,9) 55312408259,9    0      190     0.002424192 58995  Q  WS 55314456 + 8 [a.out]259,9    0      191     0.002424434 58995  G  WS 55314456 + 8 [a.out]259,9    0      192     0.002424816 58995  U   N [a.out] 1259,9    0      193     0.002424992 58995  I  WS 55314456 + 8 [a.out]259,9    0      194     0.002425247 58995  D  WS 55314456 + 8 [a.out]259,9    0      195     0.002432434     0  C  WS 55314456 + 8 [0]

read time out解决方法_quot;read-on-writequot; in InnoDB相关推荐

  1. kali安装vscode和无法启动解决方法

    一.安装 1)源安装 使用如下命令来增加源: curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > m ...

  2. mysql error number 1130,[转]mysql error number 1130的解决方法

    关键字: is not allowed to connect to this MySQL server 如果你想连接你的mysql的时候发生这个错误: ERROR 1130: Host '192.16 ...

  3. Tomcat内存溢出解决方法

    Java内存溢出详解 一.常见的Java内存溢出有以下三种: 1. java.lang.OutOfMemoryError: Java heap space ----JVM Heap(堆)溢出 JVM在 ...

  4. ubuntu 系统 apt-get install python3-pip 依赖报错解决方法

    1. 直接安装报依赖错误 直接使用 apt-get install python3-pip 安装 sudo apt-get install python3-pip 报以下依赖错误 ubuntu@ubu ...

  5. ThInkPHP验证码不显示,解决方法汇总

    出现ThInkPHP验证码不显示的情况 官方提示如下:如果无法显示验证码,请检查: ① PHP是否已经安装GD库支持: ② 输出之前是否有任何的输出(尤其是UTF8的BOM头信息输出):(打开验证码文 ...

  6. 新安装Ubuntu加载时提示“为/检查磁盘时发生严重错误”的解决方法

    本文部分内容转载自: http://jingyan.baidu.com/article/0aa22375bbffbe88cc0d6419.html http://www.aichengxu.com/v ...

  7. 【转】android错误 aapt.exe已停止工作的解决方法

    http://www.jb51.net/article/57420.htm 在使用eclipse进行安卓java的编程的时候,有时候我们会遇到这样的问题:那就是无故弹出aapt.exe停止工作的提示, ...

  8. There is no Citrix MetaFrame server configured on the specified address错误的解决方法

    环境:windows server 2003 enterprise +Citrix MetaFrame XP Server for Windows with Feature Release 3+Met ...

  9. vs2008与IIS 7.0使用在vista上时出现的问题及解决方法(Internet Explorer 无法显示该页面)(VS2008: IE Cannot Display Web Page)...

    我的系统是Vista Ultimate SP1,先安装了vs2008 ,然后再安装了IIS7.0之后就出现了一系列的问题. 问题:通过vs2008启动程序调试时报错.错误提示为:Internet Ex ...

最新文章

  1. Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
  2. MySQL笔记1:考察内链接、左连接、右连接。
  3. centos7安装mysql8.0简书_【Linux实战03】CentOS 7 下 MySQL 8.0 的安装
  4. boost::python::detail::is_borrowed_ptr相关的测试程序
  5. 高并发系统—通用设计方法
  6. 《异构信息网络挖掘: 原理和方法(1)》一第2章 基于排名的聚类
  7. python excel操作库,可能是全网最完整的 Python 操作 Excel库总结!
  8. python入门心得_一天入门 Python 的一些心得
  9. jQuery中的动画理论干货
  10. OpenShift 4 之Istio-Tutorial (4) 流量控制和灰度发布
  11. fiddler限速/弱网模拟
  12. scala写入mysql_spark rdd转dataframe 写入mysql的实例讲解
  13. SQL动态配置,动态解析SQL
  14. quartz定时任务时间设置
  15. delphi 组件安装教程详解
  16. 關於小米路由器老毛子Padavan固件之使用
  17. paper report: DIRT-T
  18. linux温湿度传感器SHTC3驱动开发
  19. Android composse 声明式UI,更简单的自定义
  20. Typora图床设置

热门文章

  1. utilities(C++)——枚举
  2. convenient functions in numpy
  3. python中对象的概念是什么_python面向对象编程的基本概念
  4. php 判断 pc 移动设备,PHP判断是移动设备还是PC设备
  5. python资料-python 资料
  6. python发音模块-python声音模块
  7. python语言入门-Python语言入门.pdf
  8. python画超长图-Python 拼接多张尺寸大小不一样的图片制作长图
  9. python编程软件哪个好-来 看看谁最适合学Python编程
  10. python numpy安装步骤-NumPy 安装