MySQL 8.0 引入 innodb_flush_method 等新参数的系统调用分析
本文我们将讨论如何在操作系统级别验证 innodb_flush_method
和 innodb_use_fdatasync
修改为默认值之外的其它值(特别是 O_DIRECT 是最常用的)后的效果。
介绍
首先,让我们定义该 innodb_flush_method
参数的作用。它规定了 InnoDB 如何管理数据刷新到磁盘的行为。文章不会详细说明每个有效值的作用,更多详细介绍请查看参数值文档。
有效值如下(仅限 Unix):
- fsync
- O_DSYNC
- littlesync
- nosync
- O_DIRECT
- O_DIRECT_NO_FSYNC
如前所述,我们将重点关注 O_DIRECT。作为最佳实践的一部分,我们建议选择 O_DIRECT 避免双缓冲,绕过操作系统缓存,从而提高写入数据时的性能。下面是从官方文档中摘录的 InnoDB 架构:
在支持 fdatasync()
的平台上执行系统调用(System calls,以下简称 Syscalls),MySQL 8.0.26 中引入的 innodb_use_fdatasync 变量允许使用 innodb_flush_method 选项来替代。除非后续数据检索需要,否则系统调用不会刷新对文件元数据的更改,从而提供潜在的性能优势。
要操作文件,MySQL 和任何其他软件都必须调用 Syscalls。每当进程需要系统资源时,它都会通过 Syscalls 向内核发送对该资源的请求。从较高层次来看,系统调用是内核向用户应用程序提供的“服务”。它们类似于库 API,被描述为具有名称、参数和返回值的函数调用。下图是此过程的高级说明:
问题:为什么不直接访问我们想要的资源(内存、磁盘等)?
这是因为 Linux 将进程的执行分为两个空间。用户运行的进程(一般称为用户空间进程)依赖于内核提供的服务。内核是操作系统的一个特定部分,它以特权运行模式处理各种低级操作。这里详细描述了用户空间和内核空间的概念。如果应用程序可以直接读写内核的地址空间,系统的安全性和稳定性就会受到影响。在给定的场景中,一个进程能够访问另一进程的内存区域。这表明内存隔离存在潜在问题,并可能导致安全漏洞。
问题:如何检查我的操作系统是否支持特定的 Syscalls?
$ man syscalls
它将列出可用的 Syscalls 以及其中出现的 Linux 内核。
验证
我们将使用 strace 实用程序和 /proc/<pid>/fdinfo/<fdinfo>
中提供的信息来证明前面描述的理论。首先,我将使用默认设置启动一个 MySQL 8.0.33 实例。
mysqld 我们可以通过检查 /proc/<pid>/fd/
列出进程打开的文件:
$ ls -l /proc/12006/fd/ total 0 lr-x------. 1 vinicius.grippa percona 64 Jan 15 16:59 0 -> /dev/null l-wx------. 1 vinicius.grippa percona 64 Jan 15 16:59 1 -> /home/vinicius.grippa/sandboxes/msb_8_0_33/data/msandbox.err ... lrwx------. 1 vinicius.grippa percona 64 Jan 15 16:59 9 -> /home/vinicius.grippa/sandboxes/msb_8_0_33/data/#ib_16384_1.dblwr
我们可以通过运行这个命令,来检查每个文件描述符 cat /proc/<pid>/fdinfo/<file descriptor number>
:
$ cat /proc/12006/fdinfo/9 pos: 0 flags: 0100002 mnt_id: 69 lock: 1: POSIX ADVISORY WRITE 12006 fd:06:32640985 0 EOF
我们对八进制数表示的标志描述感兴趣。要解释这些标志,我们可以使用 GitHub 中的 fdflags 存储库或在 shell 中使用以下命令:
$ for flag in APPEND ASYNC CLOEXEC CREAT DIRECT DIRECTORY DSYNC EXCL LARGEFILE NOATIME NOCTTY NOFOLLOW NONBLOCK PATH RDWR SYNC TMPFILE TRUNC; do printf '%s: ' O_${flag}; echo O_${flag} | gcc -D_GNU_SOURCE -include fcntl.h -E - | tail -n 1; done
并使用 fdflags 项目来避免手动工作:
fdinfo_directory="/proc/46211/fdinfo/" fd_directory="/proc/46211/fd/" for fd in $(ls ${fdinfo_directory}); do echo "Processing file descriptor ${fd}" && # Read the symbolic link to find out the file name file_name=$(readlink "${fd_directory}${fd}") echo "File Name: $file_name" ./fdflags "${fdinfo_directory}${fd}" done
# Output Processing file descriptor 5 File Name: /home/vinicius.grippa/sandboxes/msb_8_0_33/data/test/sbtest79.ibd O_LARGEFILE O_RDWR ... Processing file descriptor 99 File Name: /home/vinicius.grippa/sandboxes/msb_8_0_33/data/test/sbtest89.ibd O_LARGEFILE O_RDWR
输出显示文件描述符编号、文件名以及打开时应用于该文件的标志。
接下来,我们可以确认 MySQL 正在使用 strace 的 fsync()
来写入数据:
# Attaching strace to the mysqld process $ strace -f -c -o ./strace.out -p <pid>
# Once you exit strace (CTRL+C), a summary of syscalls is written in the strace.out file $ cat strace.out % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 45.38 222.980851 1158 192526 50579 futex 27.50 135.114996 134309 1006 io_getevents 5.90 28.997398 1933159 15 12 restart_syscall 5.69 27.970912 537902 52 nanosleep 5.32 26.117827 122 213323 2088 read 3.86 18.968682 172 109744 write 3.00 14.731474 1133190 13 epoll_wait 1.13 5.565184 574 9688 fsync 0.82 4.050227 134 30132 clock_gettime 0.61 2.974088 148 20089 pwrite64 0.47 2.311729 708 3264 fdatasync ... 0.00 0.000270 135 2 rename 0.00 0.000256 32 8 close ------ ----------- ----------- --------- --------- ---------------- 100.00 491.324073 590620 52679 total
即使没有启用 innodb_use_fdatasync
,您也会在 strace 输出中注意到 Syscalls。当 sync_binlog >0 时,系统调用默认被二进制日志使用。我们可以在 strace 中确认:
$ strace -f -s2048 -yy -o ./strace.out -p <pid> ... 47252 fdatasync(70</home/vinicius.grippa/sandboxes/msb_8_0_33/data/binlog.000026> <unfinished ...>
建议:尝试设置 sync_binlog=0 并检查
fdatasync()
执行时,MySQL 是否仍然请求系统调用来获取二进制日志。
现在,我们将向 MySQL 添加以下设置并重新启动实例:
[mysqld] innodb_flush_method=O_DIRECT innodb_use_fdatasync = ON
再次检查,我们可以看到 O_DIRECT 文件中添加了一个新标志 :
Processing file descriptor 96 File Name: /home/vinicius.grippa/sandboxes/msb_8_0_33/data/test/sbtest112.ibd O_LARGEFILE O_RDWR O_DIRECT … Processing file descriptor 99 File Name: /home/vinicius.grippa/sandboxes/msb_8_0_33/data/test/sbtest94.ibd O_LARGEFILE O_RDWR O_DIRECT
并使用 strace 检查,我们将使用以下命令看到我们的表文件(*.ibd):
$ strace -f -s2048 -yy -o ./strace.out -p 20498 ... 20551 fdatasync(48</home/vinicius.grippa/sandboxes/msb_8_0_33/data/test/sbtest23.ibd> <unfinished ...> 20551 fdatasync(26</home/vinicius.grippa/sandboxes/msb_8_0_33/data/test/sbtest5.ibd> <unfinished ...> 20550 fdatasync(34</home/vinicius.grippa/sandboxes/msb_8_0_33/data/test/sbtest15.ibd> <unfinished ...> 20550 fdatasync(24</home/vinicius.grippa/sandboxes/msb_8_0_33/data/test/sbtest1.ibd> <unfinished ...>
结论
我们研究了 InnoDB 数据刷新机制的技术细微差别以及它们如何与操作系统交互。innodb_flush_method
我们可以通过调整参数和 .sql
文件 innodb_use_fdatasync
来了解优化 MySQL 性能的细节。
我们使用 strace 实用程序进行的实验以及检查文件描述符的实验 /proc/<pid>/fdinfo/
提供了调整这些设置时行为发生变化的具体证据。使用可以带来更高效的数据写入操作。此外,MySQL 8.0.26 中的引入及其 在特定场景中的偏好说明了 MySQL 的不断发展,以利用特定的系统调用优势来提高性能。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。
SQLE 获取

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
深分页怎么导致索引失效了?提供6种优化的方案!
深分页怎么导致索引失效了?提供6种优化的方案! 上篇文章说到索引失效的几种规则,其中就有包括 深分页回表太多导致索引失效 的场景 本篇文章来聊聊深分页场景中的问题并提供几种优化方案,以下是本篇文章的思维导图: 深分页问题 那么什么是深分页问题呢? 在MySQL的limit中:limit 100,10MySQL会根据查询条件去存储引擎层找到前110条记录,然后在server层丢弃前100条记录取最后10条 这样先扫描完再丢弃的记录相当于白找,深分页问题指的就是这种场景(当limit的偏移量过大时会导致性能开销) -- 0.04s select SQL_NO_CACHE * from student where age = 18 limit 10; -- 4.049s select SQL_NO_CACHE * from student where age = 18 limit 5000,10; 该表中存在二级索引:idx_age_name 是学生年龄age和学生名称name的联合索引(该二级索引上只存在字段age,name,id) 这条SQL会基于MySQL最优成本选择使用 idx_ag...
- 下一篇
提升编码幸福感的秘密「GitHub 热点速览」
写代码是一个充满挑战的事情,在这段充满挑战的旅途中,我们都渴望找到那个提升幸福感的秘密。没准是更先进或是更快的工具,希望本期热点速递的开源项目,能给你带来启迪和乐趣,上菜! 第一个上场的是一款用 Rust 写的代码编辑器:Zed,因为它足够快、足够先进。全栈不等于全占 Expo 让你用一套代码到处运行,轻松拿下客户端。用过 Git 的小伙伴都知道,起项目时一个好的 .gitignore 文件能让你省去好多烦恼,GitHub 官方维护的 gitignore 拿去直接用。最后,热评的 JSON 可视化工具 JSON Crack 也不要错过呀! 对了,贾扬清博士开源的对话式 AI 搜索工具(Demo)有时间也可以玩一下,感受下新型搜索工具的交互模式。 本文目录 1. 开源新闻 1.1 500 行对话式 AI 搜索工具 1.2 “被”下架的开源项目 2. GitHub 热搜项目 2.1 超快的代码编辑器:Zed 2.2 快速开发移动端:Expo 2.3 用 Python 画架构图:Diagrams 2.4 Git 忽略文件的集合:gitignore 2.5 大语言模型课程:LLM-course...
相关文章
文章评论
共有0条评论来说两句吧...