MySQL 8.0 引入 innodb_flush_method 等新参数的系统调用分析

2024-01-30 11:04

本文主要是介绍MySQL 8.0 引入 innodb_flush_method 等新参数的系统调用分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文我们将讨论如何在操作系统级别验证 innodb_flush_methodinnodb_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}); doecho "Processing file descriptor ${fd}" &&# Read the symbolic link to find out the file namefile_name=$(readlink "${fd_directory}${fd}")echo "File Name: $file_name"./fdflags "${fdinfo_directory}${fd}"        
done
# OutputProcessing 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 正在使用 stracefsync() 来写入数据:

# 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 futex27.50  135.114996      134309      1006           io_getevents5.90   28.997398     1933159        15        12 restart_syscall5.69   27.970912      537902        52           nanosleep5.32   26.117827         122    213323      2088 read3.86   18.968682         172    109744           write3.00   14.731474     1133190        13           epoll_wait1.13    5.565184         574      9688           fsync0.82    4.050227         134     30132           clock_gettime0.61    2.974088         148     20089           pwrite640.47    2.311729         708      3264           fdatasync
...0.00    0.000270         135         2           rename0.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 获取

类型地址
版本库https://github.com/actiontech/sqle
文档https://actiontech.github.io/sqle-docs/
发布信息https://github.com/actiontech/sqle/releases
数据审核插件开发文档https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse

这篇关于MySQL 8.0 引入 innodb_flush_method 等新参数的系统调用分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/660035

相关文章

数据库面试必备之MySQL中的乐观锁与悲观锁

《数据库面试必备之MySQL中的乐观锁与悲观锁》:本文主要介绍数据库面试必备之MySQL中乐观锁与悲观锁的相关资料,乐观锁适用于读多写少的场景,通过版本号检查避免冲突,而悲观锁适用于写多读少且对数... 目录一、引言二、乐观锁(一)原理(二)应用场景(三)示例代码三、悲观锁(一)原理(二)应用场景(三)示例

SQL表间关联查询实例详解

《SQL表间关联查询实例详解》本文主要讲解SQL语句中常用的表间关联查询方式,包括:左连接(leftjoin)、右连接(rightjoin)、全连接(fulljoin)、内连接(innerjoin)、... 目录简介样例准备左外连接右外连接全外连接内连接交叉连接自然连接简介本文主要讲解SQL语句中常用的表

SQL server配置管理器找不到如何打开它

《SQLserver配置管理器找不到如何打开它》最近遇到了SQLserver配置管理器打不开的问题,尝试在开始菜单栏搜SQLServerManager无果,于是将自己找到的方法总结分享给大家,对SQ... 目录方法一:桌面图标进入方法二:运行窗口进入方法三:查找文件路径方法四:检查 SQL Server 安

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

MySQL 中的 LIMIT 语句及基本用法

《MySQL中的LIMIT语句及基本用法》LIMIT语句用于限制查询返回的行数,常用于分页查询或取部分数据,提高查询效率,:本文主要介绍MySQL中的LIMIT语句,需要的朋友可以参考下... 目录mysql 中的 LIMIT 语句1. LIMIT 语法2. LIMIT 基本用法(1) 获取前 N 行数据(

MySQL 分区与分库分表策略应用小结

《MySQL分区与分库分表策略应用小结》在大数据量、复杂查询和高并发的应用场景下,单一数据库往往难以满足性能和扩展性的要求,本文将详细介绍这两种策略的基本概念、实现方法及优缺点,并通过实际案例展示如... 目录mysql 分区与分库分表策略1. 数据库水平拆分的背景2. MySQL 分区策略2.1 分区概念

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分