0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MySQL缓冲区设计介绍

数据分析与开发 来源:博客 作者:Spongecaptain's 2021-10-15 09:50 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1. Buffer 与 cache 的区别?

Bbuffer 与 Cache 非常类似,因为它们都用于存储数据数据,被应用层读取字节数据。在很多场合它们有着相同的概念,但是特定场合也有一定的区别[1]。

Buffer 与 Cache 的用途有所不一定:

Buffer 的主要目的是在不同应用、线程、进程之间共享字节数据,例如为了让不同速度的设备能够进行数据同步,就会使用共享 Buffer;

Cache 的主要目的是提高字节数据的读取/写入速度,例如根据时间局部性、地址局部性操作系统提供 page cache 机制;

当然,在很多场合下 Buffer 与 Cache 有着相同的语义,因此我们可以认为缓冲区既用于提高读写速度,又用于数据共享与同步。

2. MySQL 缓冲区设计

Figure1.MySQL 的缓冲区设计

如上图所示,MySQL 在不同层次使用了与缓存机制不同的配套技术。其中有:

应用层:

Redo Log Buffer:对写操作进行缓存,用于实现 MySQL InnoDB 的事务性;

InnoDB Buffer Pool:用于对 MySQL table 的数据进行缓存。读内存而不是磁盘,通过减少磁盘读操的方式提高读操作性能;写内存而不是磁盘,通过减少磁盘写操的方式提高写操作性能;

操作系统的 VFS(Virtual file system,虚拟文件系统)层:

Page Cache:操作系统通过缓存以及预读机制对文件系统中的 block 基于 page 进行缓存管理;

Direct Buffer:当使用 Direct I/O 提供的相关 API 时,操作系统不再提供基于 Page Cache 机制的缓存,而是直接使用 Direct Buffer;

磁盘的 Disk Buffer:磁盘也可以提供磁盘缓存,通常在 MySQL 中会关闭磁盘缓存,我们仅仅需要了解有 Disk Buffer 这一概念即可。

3. Write Through/Back 与 Direct I/O

Write Through 与 Write Back 指的是在使用内存空间作为缓存的应用在处理写操作时是否直接落盘:

Write Through:写操作“穿过”缓存区直接落盘,这种策略能够确保数据不会因为宕机而丢失内存缓冲区的数据;

Write Back:一次写操作仅仅更新了内存缓存区中的数据,数据落盘通常通过间隔一个时间进行落盘一次;

MySQL 为此提供了一些参数来控制 Page Cache 数据落盘的具体行为,例如:

(1)innodb_flush_log_at_trx_commit

innodb_flush_log_at_trx_commit 参数用于控制基于 Page Cache 的 Redo Log Buffer 的数据落盘机制[2]。此参数用于控制以下两个特性之间的平衡:

严格的事务管理机制;

事务提交 commit 操作执行时的高性能;

innodb_flush_log_at_trx_commit 有三个可选配置值:

1(默认值):每次事务提交时都日志必须刷新到磁盘上,提供了最可靠的事务性保证;

0:日志每间隔 1 秒刷新到磁盘上,这意味着在缓存中还没有来得及刷新到磁盘上的数据在宕机时会丢失;

2:日志在事务提交后以及每间隔 1 秒刷新到磁盘上,这意味着在缓存中还没有来得及刷新到磁盘上的数据在宕机时会丢失;

注意事项:配置 0 与 2 并不能保证 100% 每间隔一秒刷新到磁盘一次,这是因为 DDL 的修改以及 InnoDB 活动可能会导致日志刷新更频繁。另一方面,由于事务调度问题,刷新频率甚至会降低。

刷新频率默认为 1 s,由参数 innodb_flush_log_at_timeout 进行配置。

(2)innodb_flush_method

innodb_flush_method 参数同时控制 redo log buffer 和 innodb buffer pool 缓冲区刷新策略,其中:

log files:redo log buffer 是 log files 在内存中的缓存区, log files 是磁盘上的 Redo Log 文件;

data files:innodb buffer pool 是 data files 在内存中的缓存区,data files 是磁盘上的数据文件(B+tree);

innodb_flush_method 参数目前有 6 种可选配置值[3]:

fdatasync;

O_DSYNC

O_DIRECT

O_DIRECT_NO_FSYNC

littlesync

nosync

这里只讨论 Unix-like 操作系统,而不讨论 Windows 系统。

其中,littlesync 与 nosync 仅仅用于内部性能测试,并不建议使用。

fdatasync,即取值 0,这是默认配置值。对 log files 以及 data files 都采用 fsync 的方式进行同步;

O_DSYNC,即取值 1。对 log files 使用 O_SYNC 打开与刷新日志文件,使用 fsync 来刷新 data files 中的数据;

O_DIRECT,即取值 4。利用 Direct I/O 的方式打开 data file,并且每次写操作都通过执行 fsync 系统调用的方式落盘;

O_DIRECT_NO_FSYNC,即取值 5。利用 Direct I/O 的方式打开 data files,但是每次写操作并不会调用 fsync 系统调用进行落盘;

补充说明:以 O_SYNC 方式打开文件意味着文件的每一次写操作都直接导致将数据本身以及元数据刷新到磁盘上。

为什么有 O_DIRECT 与 O_DIRECT_NO_FSYNC 配置的区别?

首先,我们需要理解更新操作落盘分为两个具体的子步骤:①文件数据更新落盘②文件元数据更新落盘。O_DIRECT 的在部分操作系统中会导致文件元数据不落盘,除非主动调用 fsync,为此,MySQL 提供了 O_DIRECT 以及 O_DIRECT_NO_FSYNC 这两个配置[5]。

如果你确定在自己的操作系统上,即使不进行 fsync 调用,也能够确保文件元数据落盘,那么请使用 O_DIRECT_NO_FSYNC 配置,这对 MySQL 性能略有帮助。否则,请使用 O_DIRECT,不然文件元数据的丢失可能会导致 MySQL 运行错误。

4. MySQL 日志的刷新策略

MySQL 日志刷新策略通过 sync_binlog 参数进行配置,其有 3 个可选配置:

sync_binlog=0:MySQL 应用将完全不负责日志同步到磁盘,将缓存中的日志数据刷新到磁盘全权交给操作系统来完成;

sync_binlog=1:MySQL 应用在事务提交前将缓存区的日志刷新到磁盘;

sync_binlog=N:当 N 不为 0 与 1 时,MySQL 在收集到 N 个日志提交后,才会将缓存区的日志同步到磁盘。

事实上,这个参数也用于控制日志是通过 Write Through 还是 Write Back 策略刷新到磁盘上。

注意事项:使用 Page Cache 机制的数据刷盘机制,即使基于同步策略,即每次写操作都要求数据直接落盘,但在数据落盘之前,数据总是先要写于 Page Cache 中,再将 Page Cache 中的具体 Page 刷新到磁盘上。

5. MySQL 的典型配置

innodb_flush_log_at_trx_commit 参数配置为 1:Redo Log 走 Page Cache,并且每次写操作的日志在事务提交前都通过 fsync 刷新到磁盘;

innodb_flush_method 参数配置为 O_DIRECT:InnoDB Buffer Pool 走 Direct I/O,并且每次写操作导致的文件数据(包括文件元数据)都通过 fsync 系统调用刷新到磁盘;

写一条 redo log 涉及到的步骤有:

日志写入 Redo Log buffer;

日志写入 Page Cache;

通过系统调用 fsync 将 Page Cache 中的脏页刷新到磁盘;

日志提交;

修改表的一行记录涉及到的步骤有:

更新后的数据写于 InnoDB Buffer Pool;

定时进行如下逻辑(异步进行):

InnoDB Buffer Pool 脏数据进行刷新,通过文件的 write 方法进行;

文件的 write 方法直接导致数据写于磁盘上;

定时进行文件的 fysnc 调用,确保文件元数据写于磁盘上;

https://spongecaptain.cool/post/mysql/zerocopyofmysql/

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    7316

    浏览量

    94044
  • MySQL
    +关注

    关注

    1

    文章

    897

    浏览量

    29251

原文标题:MySQL 的零拷贝技术

文章出处:【微信号:DBDevs,微信公众号:数据分析与开发】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    CW32L052串口的缓冲区机制

    默认缓冲区配置 CW32L052的UART模块支持硬件FIFO(通常为16字节),但HAL库或用户代码需手动管理接收缓冲区。若未显式分配足够大的软件缓冲区,可能导致数据溢出。 HAL库缓冲区
    发表于 11-24 06:40

    飞凌嵌入式ElfBoard-标准IO接口之设置缓冲区

    1.setvbuf 用于以对文件的 stdio 缓冲区进行设置,譬如缓冲区缓冲模式、缓冲区的大小、起 始地址等。 1)头文件 #include 2)函数原型 int setvbuf
    发表于 11-14 09:02

    移植的lvgl,在运行的时候,缓冲区无法释放怎么解决?

    代码在运行的时候,只有lvgl线程用于刷新,另一个线程只有一个串口打印。 当运行一段时间后,发现,程序会在LVGl中,lv_refr.c这个库下面第625行代码, 在这一直判断,看介绍说是在等待释放缓冲区,求大神给个思路
    发表于 09-09 07:28

    USB缓冲区中的内容满了之后,是否有标志位进行反馈?

    USB缓冲区中的内容满了之后,是否有标志位进行反馈。
    发表于 07-17 07:13

    请问USB缓冲区取数据可以多次取吗?

    在使用USB软件获取数据是,下位机给我发送了13个32位数据到USB IN缓冲区,为什么我调用API函数想要第一次取1个32位数据,取完之后再取12位数据,程序会卡死。
    发表于 07-16 08:12

    解析RZ/N2L CANFD模块的缓冲区机制(2)

    在工业自动化、智能交通、机器人等领域,CANFD(CAN with Flexible Data-Rate)技术正逐步取代传统CAN,以适应更高的数据速率和更复杂的通信需求。本文将深入解析RZ/N2L CANFD模块的缓冲区机制,帮助工程师更高效地管理CAN消息,提高系统性能。
    的头像 发表于 05-19 14:13 1178次阅读
    解析RZ/N2L CANFD模块的<b class='flag-5'>缓冲区</b>机制(2)

    解析RZ/N2L CANFD模块的缓冲区机制(1)

    在工业自动化、智能交通、机器人等领域,CANFD(CAN with Flexible Data-Rate)技术正逐步取代传统CAN,以适应更高的数据速率和更复杂的通信需求。本文将深入解析RZ/N2L CANFD模块的缓冲区机制,帮助工程师更高效地管理CAN消息,提高系统性能。
    的头像 发表于 05-19 14:10 997次阅读
    解析RZ/N2L CANFD模块的<b class='flag-5'>缓冲区</b>机制(1)

    FX3 Socket缓冲区切换的最大时间是多少?

    FX3_Programmers_Manual 文档的第 10 章提到“每个缓冲区缓冲区切换开销为 550 - 900 ns”。 Getting_Started_with_EZ-USB_FX3 文档
    发表于 05-16 07:51

    在传输DMA通道中的所有缓冲区后,DMA标志(就绪和部分)被卡住了是怎么回事?

    是,旗帜最初的表现是正确的。 它们被配置为 ACTIVE HIGH 标志,初始值设为 LOW。 整个 DMA 通道默认使用两个 DMA 缓冲区。 传输开始时,第一个缓冲区被正确填满:部分标志(标志 b
    发表于 05-16 07:18

    求助,关于3014的缓冲区设置疑问求解

    rgb24 1080p@60fps是静态图像,dma缓冲区的配置即大小和数量分别为16kb,6,沿用的是yuy2的配置,但yuy2 1080p@60fps 是动态且不颠倒,是否可以认为是由于缓冲区
    发表于 05-06 13:42

    请问如何在Linux中使用帧缓冲区更新epdc显示?

    我正在使用带有 epdc 显示子卡 (IMXEBOOKDC5) 的 IMX8ULP EVK。使用 Linux 映像引导后,epdc 显示无法使用帧缓冲区进行更新。当检查显示 pmic 的电源使能引脚
    发表于 04-01 06:41

    FreeRTOS进阶使用之流缓冲区:高效处理字节流的秘密武器

    在嵌入式开发中,流缓冲区(Stream Buffer)是FreeRTOS中用于高效处理字节流数据传输的核心机制,尤其适合任务间或中断与任务间的连续数据传输场景(如串口通信、网络数据流等)。本文将深入
    发表于 03-24 11:37

    L9663如何使用上行缓冲区发送同步脉冲?

    我根据L9663 Datasheet这个手册,想使用这个配置“通过带有上行数据缓冲区的SPI触发。微控制器发送相应的SPI命令以发送同步脉冲。然后,同步脉冲触发发生器根据上行数据缓冲区中的值在内部
    发表于 03-13 08:15

    缓冲区溢出漏洞的原理、成因、类型及最佳防范实践(借助Perforce 的Klocwork/Hleix QAC等静态代码分析工具)

    本期来认识软件漏洞的“常客”——缓冲区溢出,C/C++开发者尤其要注意!全面了解该漏洞的成因、类型、常见示例,以及如何借助Klocwork、Helix QAC等SAST工具进行防护。
    的头像 发表于 03-04 16:39 1769次阅读
    <b class='flag-5'>缓冲区</b>溢出漏洞的原理、成因、类型及最佳防范实践(借助Perforce 的Klocwork/Hleix QAC等静态代码分析工具)

    RTOS的流缓冲区机制解析

    SAFERTOS中的流缓冲区(Stream buffer)机制,可以实现任务到任务或中断到任务之间的通信。字节流是由发送方写入缓冲区,接收方读取缓冲区数据。流缓冲区作为队列的轻量级级替
    的头像 发表于 02-14 11:33 1007次阅读
    RTOS的流<b class='flag-5'>缓冲区</b>机制解析