[MySQL 5.6] double write buffer的几个关键函数

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

一个double write buffer 有2MB, 共128个page,在MySQL 5.6中, 默认有120个page用于批量刷新(如 LRU Flush 或者FLUSH LIST FLUSH),剩下的8个Page用于单个page的flush。

在DEBUG版本下,120是可以通过参数innodb_doublewrite_batch_size来配置的,好吧。我已经不安分的把DEBUG宏给去掉了。
全局对象buf_dblwr, 对应结构体为buf_dblwr_t:
ib_mutex_t  mutex 互斥量
ulint block1 第一个doubewrite 块(64个page)的page no
ulint block2 第二个double write 块的page no
ulint first_free 在write_buf中第一个空闲的位置
ulint s_reserved  为单个page刷新预留的slot数,当flush类型为BUF_FLUSH_SINGLE_PAGE时,会进入到函数buf_dblwr_write_single_page来写一个Page 
ulint b_reserved  为batch flush 预留的slot数
ibool*  in_use 用于标记一个slot是否被使用,只用于single page flush 
ibool batch_running  当设置为TRUE时,表明有一次batch flush正在进行
byte*  write_buf double write buffer在内存的缓存,以UNIV_PAGE_SIZE对其
byte*  write_buf_unaligned  未对齐的write_buf
buf_page_t**  buf_block_arr  存储已经cache到write_buf的block的指针


这里解释一下FLUSH操作的类型,总的来说,有三种刷新类型
BUF_FLUSH_LRU:表示从Buffer Pool的LRU上扫描并刷新
BUF_FLUSH_LIST:表示从Buffer Pool的FLUSH LIST上扫描并刷新
BUF_FLUSH_SINGLE_PAGE:从LRU上只刷新一个Page 
前两种属于BATCH FLUSH, 最后一种属于SINGLE FLUSH
BUF_FLUSH_SINGLE_PAGE在几种情况下使用到:
1.buf_flush_or_remove_page
2.buf_flush_single_page_from_LRU,这在FREE LIST不够用时,IO-bound场景下,可能频繁调用到(buf_LRU_get_free_block)
3.buf_flush_page_try
 
TODO:下一篇博客再介绍这几种刷page的类型

quoted code in buf_flush_write_block_low

 938         if (!srv_use_doublewrite_buf || !buf_dblwr) {

 939                 fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
 940                        FALSE, buf_page_get_space(bpage), zip_size,
 941                        buf_page_get_page_no(bpage), 0,
 942                        zip_size ? zip_size : UNIV_PAGE_SIZE,
 943                        frame, bpage);
 944         } else if (flush_type == BUF_FLUSH_SINGLE_PAGE) {
 945                 buf_dblwr_write_single_page(bpage);
 946         } else {
 947                 buf_dblwr_add_to_batch(bpage);
 948         }
这里根据flush的类型来判断对应的逻辑,如果刷新类型为BUF_FLUSH_SINGLE_PAGE,则调用buf_dblwr_write_single_page,否则调用buf_dblwr_add_to_batch
A.
buf_dblwr_write_single_page(page):用于将一个page加入到double write buffer中,并完成写操作
主要流程如下:
1.

最大为单个page刷新预留的dblwr  page数为:

2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE-srv_doublewrite_batch_size

默认为8个page

当s_reserved值等于最大page数量时,线程会去sleep后retry
2.从srv_doublewrite_batch_size开始,找到一个buf_dblwr->in_use[i] 不为TRUE的slot。分配给当前page
将in_use[i]设为TRUE,并递增s_reserved++
3.将单个page写入到double write buffer中。注意,这里已经释放了buf_dblwr->mutex
4.刷double write buffer (fil_flush(TRX_SYS_SPACE)),然后再将数据写入到磁盘中(buf_dblwr_write_block_to_datafile,buf_flush_sync_datafiles)
注意在函数buf_flush_sync_datafiles中会唤醒IO线程,等待写入完成,因此这是同步写操作
5.再次持有buf_dblwr->mutex,将s_reserved–, in_use[i], buf_block_arr[i]置为NULL。
B.
buf_dblwr_add_to_batch(bpage):将一个page加入到double write buffer中,如果batch满了,则刷double write buffer到磁盘
该函数的逻辑如下:
1.持有buf_dblwr->mutex
2.如果batch_running为TRUE,表示已经有人在开始做batch flush来刷dblwr,释放互斥锁,sleep一段时间后,回到1retry
3.如果batch满了(即buf_dblwr->first_free == srv_doublewrite_batch_size),则释放mutex, 主动调用buf_dblwr_flush_buffered_writes()把dblwr的写到磁盘,然后回到1   retry
4. 将page拷贝到第buf_dblwr->first_free个槽位,并设置:
buf_dblwr->buf_block_arr[buf_dblwr->first_free] = page;
buf_dblwr->first_free++;
buf_dblwr->b_reserved++;
5.再次检查batch flush的槽位是否已满(buf_dblwr->first_free == srv_doublewrite_batch_size) ,如果满了,则释放mutex,进行一次flush(buf_dblwr_flush_buffered_writes()),从函数返回
  
6.最后释放mutex.
C.
buf_dblwr_flush_buffered_writes() : 批量刷double write buffer的函数(只涉及batch flush的page)
 
流程如下:
1.持有buf_dblwr->mutex
2.如果fist_free为0,表示当前double write buffer为空,释放mutex,返回
3.如果batch_running为TRUE,表示正有线程在做batch flush,释放Mutex, sleep一段时间后回到1 retry
4.将batch_running设置为TRUE,避免并发写
5.释放buf_dblwr->mutex
6.检查每一个将要写dblwr的block以及write_buf中的page是否被损坏或者LSN值是否正确
buf_dblwr_check_block(block) 以及 buf_dblwr_check_page_lsn(write_buf + len2)
7.将write_buf中的page写入到文件中
先写第一个block(<=64个page),再写第二个block(<=64个page),
也就是说最多一次写入1M, 分两次写的原因是??
8.将double write buffer刷到磁盘后(fil_flush(TRX_SYS_SPACE);),逐个开始写数据文件(OS_AIO_SIMULATED_WAKE_LATER)

 866                 buf_dblwr_write_block_to_datafile(

 867                         buf_dblwr->buf_block_arr[i]);
9.唤醒IO线程(os_aio_simulated_wake_handler_threads)

注意这里,在函数结束时并没有将batch_running设置为FALSE,因为这里对数据文件做的是异步写,设置标记位的工作留给了IO线程来完成

io_handler_thread-> fil_aio_wait-> buf_page_io_complete->buf_flush_write_complete->buf_dblwr_update():
看起来在double write buffer中,BATCH FLUSH 和SINGER PAGE FLUSH对应的slot非常独立,那么我们是否可以把这个mutex拆成两个呢? 

简单的测试了一把,结果是。。。。。差别不大
我把自己的想法提到buglist上了,不知道官方的怎么看。。。
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
JSON 关系型数据库 MySQL
Mysql(5)—函数
MySQL提供了许多内置的函数以帮助用户进行数据操作和分析。这些函数可以分为几类,包括聚合函数、字符串函数、数值函数、日期和时间函数、控制流函数等。
93 1
Mysql(5)—函数
|
2天前
|
SQL 关系型数据库 MySQL
【MySQL基础篇】盘点MySQL常用四大类函数
本文介绍了MySQL中的四大类常用函数:字符串函数、数值函数、日期函数和流程函数。
【MySQL基础篇】盘点MySQL常用四大类函数
|
2天前
|
存储 人工智能
AscendC编程中的double buffer是什么?
在AI Core上,指令队列分为Vector(V)、Matrix(M)和存储移动指令队列(MTE2、MTE3)。这些队列的独立性和可并行性是double buffer优化的基础。通过将数据搬运与Vector计算并行执行,double buffer机制有效减少了Vector单元的等待时间,提高了其利用率。例如,Tensor1进行Compute时,Tensor2可同时执行CopyIn;当切换到Tensor2计算时,Tensor1执行CopyOut。此机制适用于大多数场景,但在数据搬运时间短或数据量小的情况下,性能提升可能有限。
|
11天前
|
存储 关系型数据库 MySQL
double ,FLOAT还是double(m,n)--深入解析MySQL数据库中双精度浮点数的使用
本文探讨了在MySQL中使用`float`和`double`时指定精度和刻度的影响。对于`float`,指定精度会影响存储大小:0-23位使用4字节单精度存储,24-53位使用8字节双精度存储。而对于`double`,指定精度和刻度对存储空间没有影响,但可以限制数值的输入范围,提高数据的规范性和业务意义。从性能角度看,`float`和`double`的区别不大,但在存储空间和数据输入方面,指定精度和刻度有助于优化和约束。
|
18天前
|
SQL 关系型数据库 MySQL
MySQL常见函数第二期,你都用过哪些呢 ?
本期介绍了20个常用的MySQL函数,涵盖日期处理(如CURDATE()、DATE_FORMAT())、数学运算(如ABS()、ROUND())、统计分析(如COUNT()、SUM())等,帮助提高SQL查询效率和数据处理能力。希望对大家的学习有所帮助。
59 7
|
20天前
|
关系型数据库 MySQL
MySQL常见函数第一期,你都用过哪些呢 ?
本期介绍10个常用的MySQL函数:字符串连接(CONCAT)、提取子字符串(SUBSTRING)、获取字符串长度(LENGTH)、转换大小写(UPPER、LOWER)、去除空格(TRIM)、替换字符串(REPLACE)、查找子字符串位置(INSTR)、带分隔符的字符串连接(CONCAT_WS)以及获取当前日期时间(NOW)。
56 8
|
21天前
|
数据采集 关系型数据库 MySQL
MySQL常用函数:IF、SUM等用法
本文介绍了MySQL中常用的IF、SUM等函数及其用法,通过具体示例展示了如何利用这些函数进行条件判断、数值计算以及复杂查询。同时,文章还提到了CASE WHEN语句和其他常用函数,如COUNT、AVG、MAX/MIN等,强调了它们在数据统计分析、数据清洗和报表生成中的重要性。
|
25天前
|
关系型数据库 MySQL 数据处理
【MySQL】函数
MySQL 提供了丰富的函数集,涵盖字符串处理、数值运算、日期时间操作和聚合计算等多个方面。这些函数在日常数据库操作中极为重要,通过合理使用这些函数,可以大大提高数据处理和查询的效率。用户还可以通过自定义函数,扩展 MySQL 的功能以满足特定需求。
28 3
|
27天前
|
关系型数据库 MySQL 数据处理
MySQL函数与约束
MySQL 提供了丰富的函数和强大的约束机制,用于数据处理和完整性维护。通过掌握这些工具,可以有效地管理和分析数据库中的数据,确保数据的一致性和准确性。无论是在日常数据查询中使用内置函数,还是在数据库设计中应用各种约束,都是确保数据库系统稳定、高效运行的关键。希望本文对您理解和应用 MySQL 函数与约束有所帮助。
31 1
|
1月前
|
关系型数据库 MySQL Serverless
MySQL函数
最常用的MySQL函数,包括聚合函数,字符串函数,日期时间函数,控制流函数等
37 1