mysql刷盘机制详解

目录

刷盘机制总览

log buffer(innodb的,由存储引擎分配)

binlog cache(由server分配)

buffer pool

自适应刷脏页Adaptive Flushing


刷盘机制总览

mysql刷脏数据在写redo之后,逻辑跟oracle一致,checkpoint/commit->内存中的redo到redolog文件->内存中的脏数据到数据盘。

但是mysql多一个环节,就是把binlog从binlog cache写入到binlog文件中。binlog cache不是共享内存,是为每个client分配的私有内存,是mysql server管理的。而log buffer是共享内存,由innodb管理,属于innodb存储引擎内存。

 

innodb_flush_logxxx是可能指刷redo也可能指刷binlog

innodb_xx_dirty_page_xx或者innodb_xx_page_xx是指的刷脏页的参数(buffer pool的脏页刷到磁盘中)

刷日志最重要的参数有2个

1.innodb_flush_log_at_trx_commit刷log buffer的redo到log file中

2.sync_binlog刷binlog cache的事务到binlog文件中

两个参数的默认值都是1,表示提交即写log(redolog和binlog都写),也就是mysql日志双写。

 

 

 

落盘可以从3个方向分析

binlog:

binlogcache是server为每个客户端分配的内存池,事务未提交前的数据放入binlogcache,提交后写入binlog日志文件。刷binlog的重要参数就是sync_binlog,0表示关闭写binlog,1表示每次提交便写binlog到磁盘(默认),N(N>=2)表示binlog组提交,可能丢失数据。

redolog

redo在内存中存放在logbuffer,redo写入logfile是顺序循环写的,所以会比data写快(data一般是离散写)。logbuffer的重要参数是innodb_flush_log_at_trx_commit。0表示每秒写入磁盘,可能会丢失事务;1表示每次提交就写入磁盘(默认);2表示提交或每秒写入磁盘,也不会丢失事务。

(oracle的redo从redologbuffer到redo logfile:每3秒;每有提交;切换日志;1/3满或1MB。可以看出mysql跟oracle的redo落盘机制很类似,只是细节有些区别)

data:

bufferpool中的有个change buffer,也就是”插入缓存“,缓存了二级索引的变更信息,通过合并写入二级索引减少离散IO以提高性能。

刷脏页一般发生在commit之后,redo和binlog提交之后。innodb可以根据脏页在bufferpool中的水位强制刷脏页。Adaptive Flushing根据数据库负载情况调整刷每秒应该刷多少脏页。

 

 

binlog、redolog、data刷盘详解

log buffer(innodb的,由存储引擎分配)

log buffer是缓存准备写入logfile的内存区,相当于oracle的redo log buffer

innodb_flush_log_at_trx_commit (刷redo的机制)

innodb事物提交的重要参数,取值只有0、1、2,默认为1,动态参数。

该参数是用来控制提交操作和高性能的,如果需要更高的性能,在crash时可能存在数据丢失风险,也就是不具备ACID的持久性。

0:log每秒写入磁盘。crash时可能会丢失数据(因为那些已提交完成的事物还没有落盘)

1:默认值是1,在事务提交时刷脏数据到盘

2:log每秒写入磁盘,且在每次提交时写入磁盘。此状态时也不会丢失数据。

(注意:“落盘”是磁盘返回给mysql的结果,但是磁盘也有缓存,数据写入磁盘缓存后,也会返回给数据库“已落盘”的信息。磁盘缓存取决于磁盘或磁盘整列的策略,磁盘阵列通常都有备用电池的,除非数据一致性极高的情况,一般都不会关闭磁盘或阵列的缓存)

(上面的“事物提交”不仅指commit,也包含checkpoint、ddl等,会触发“提交”的操作)

 

 

innodb_log_buffer_size

innodb_log_buffer_size:log buffer的大小,默认16M,最小1M,最大4G。

如果log buffer足够大,在事务提交之前,redolog就不需要写入logfile磁盘了。

 

innodb_log_write_ahead_size

动态参数,默认8k

write-ahead block就是指redo log page。redolog的page大小可以和innodb data page不一样,必须是操作系统块大小的整数倍,操作系统块一般默认是4K,redo log page默认是8k,innodb data page默认是16k。

 

 

 

binlog cache(由server分配)

binlog cache又server分配和管理,不是innodb。binlog cache是私有的,每个连接客户端都有。

sync_binlog(刷binlog机制)

binlog提交的重要参数。取值0、1、N(N>=2), 5.7.7及以上版本默认为1,5.7.7以下版本默认是0。动态参数。

注意跟innodb_flush_log_at_trx_commit 是不一样的,innodb_flush_log_at_trx_commit 控制的是buffer pool的redo到log file,取值仅0,1,2,含义也不一样。

 

0:关闭写binlog功能。

1:开启写binlog功能,在事务提交之前就同步binlog。这种模式下binlog不会丢失事务。默认情况、一般情况都是1。

N:开启binlog组提交, binary log commit groups。这种模式下可能丢失已提交但还未flush到binlog的事务。N越高,对性能提升越明显,丢失数据的风险也越高。

 

innodb_flush_log_at_trx_commit=1且sync_binlog=1,是mysql的默认和通用配置。redo和binlog各有用处,且保证了数据的持久性。

 

innodb_flush_log_at_timeout(binlog group commit)

group commit相关参数,只有打开group commit功能时才有效。

binlog group commit的时间间隔设置。

别搞混了,跟innodb_flush_log_at_trx_commit是2个参数,针对不同的log,虽然都是flush_log

 

 binlog_group_commit_sync_delay

group commit相关参数,只有打开group commit功能时才有效。

事务提交之前同步binlog的延时。0表示没有延时,commit和写入binlog是同时的。如果设置该值,commit是有延时的。如果sync_binlog设置为>1,那么延时就是group commit的。

这参数看上去就是增加commit延时,应该不会有人开启这个功能吧。

 

binlog_group_commit_sync_no_delay_count

group commit相关参数,只有打开group commit功能时才有效。

延时时的最大事务数(group commit), binlog_group_commit_sync_delay为0时,这个参数也无效了。

 

binlog_cache_size

binlog cache的大小,默认32k。动态参数。

如果binlog开启,server会给每个client分配binlog cache。如果总有大事物,可以把该内存池调大。show global status中的有当前binlog cache使用信息。

 

 

binlog_stmt_cache_size

默认32k,动态参数。

binlog statment cache缓存在事务中的非事务性语句。如果binlog打开,且有事务性存储引擎,server会给每个client分配binlog cache和binlog statement cache。如果经常事务中有较大的非事务语句,调大此cache可以提升一定的性能,同样在show global status中有使用信息。

 

buffer pool

buffer pool是innodb引擎的重要内存结构,相当于oracle的数据库快速缓存区data buffer cache。

change buffer(以前叫插入缓存)是buffer pool的一部分,默认占用buffer pool size的1/4,存储变更的二级索引信息。因为变更的二级索引落盘一般都是随机IO,二级索引合并后写入,可以减少随机IO的负担,这就是changebuffer存在的意义。

buffer pool还有一些其他功能和要点,比如LRU,预读read-ahead,预留resistant,预热Saving and Restoring,子池,监控等等。buffer pool详情解读:buffer pool内存结构和相关运行机制

https://blog.csdn.net/qq_40687433/article/details/111994959

 

这次重点分析刷脏页

innodb buffer pool除了加载select的page到buffer pool外,还需要刷脏数据。脏数据就是在内存已被修改,但是仍未写入磁盘的数据。

 

innodb_flush_method

Command-Line Format

--innodb-flush-method=value

System Variable

innodb_flush_method

Scope

Global

Dynamic

No

Type

String

Default Value

NULL

Valid Values (Windows)

async_unbuffered

normal

unbuffered

Valid Values (Unix)

fsync

O_DSYNC

littlesync

nosync

O_DIRECT

O_DIRECT_NO_FSYNC

 

 

如果是NULL,那么当系统是类unix时,默认为fsync,当系统是windows时,默认为async_unbuffered。

该参数是innodb的参数,影响刷buffer pool的脏数据和log buffer中的redo的方式。

类unix:

fsync:默认规则,使用fsync()刷data和log file。

O_DSYNC:使用O_DSYNC去打开和刷新log file,fsync()去耍data file。在某些unix场景可能不适用。

littlesync:内部参数,尽量不要使用

nosync:内部参数,尽量不要使用

O_DIRECT:使用O_DIRECT()打开数据文件,使用fsync()刷data和log file

O_DIRECT_NO_FSYNC:O_DIRECT()刷数据,忽略fync()请求

参数配置和最佳性能取决于mysql的环境,在确定使用哪种flush模式前应尽量充分的测试

从官方文档的innodb结构图看,O_DIRECT应该是不会过操作系统缓存,fsync应该就是要过OS cache。mysql官网对这个描述不多。先放着,下次研究IO的。

(mysql IO调度机制:https://liuzhilong.blog.csdn.net/article/details/114670467

 

innodb_page_cleaners

innodb_page_cleaners是清理脏数据线程的个数,在mysql5.7中清理线程默认是4个。当innodb_page_cleaners大于等于innodb_buffer_pool_instances时,innodb_page_cleaners会被自动设置为innodb_buffer_pool_instances相等的值。

innodb_max_dirty_pages_pct_lwm

脏页的最低水位,默认为0,非0时表示开启脏页预刷,当脏页达到innodb_max_dirty_pages_pct_lwm时刷脏页就开始了

 

innodb_max_dirty_pages_pct

innodb_max_dirty_pages_pct控制脏页在buffer pool中的百分比,默认是75,innodb就会强制刷脏页。

innodb_flush_neighbors

innodb_flush_neighbors刷一个脏page时,是否刷这个page的整个extent。0表示关闭该功能,1表示刷extent中连续的pages(默认),2表示刷整个extent中的pages。当数据在普通盘上,开启该功能可以减少IO次数,而不是在不同的时间刷page,当数据在ssd上,IO情况较好,可以考虑关闭该功能,刷整个extent会比刷一个page更慢。mysql8.0中innodb_flush_neighbors的默认值为0

innodb_lru_scan_depth

innodb_lru_scan_depth在每个buffer pool子池中扫描LRU链的脏数据刷到磁盘的深度,找到的这些脏块就会flush,后台清理线程每秒执行一次。depth越小,对性能越有利,仅当IO有空余时才考虑增大depth的值。当IO特别繁忙,特别是buffer pool很大时,可以考虑适当调小depth。cleaner线程每秒会跑 innodb_lru_scan_depth * innodb_buffer_pool_instances

 

 

自适应刷脏页Adaptive Flushing

自适应刷脏页算法可以自动调节刷脏页的频率,频率取决于redo的生成和当前刷脏页的频率

该算法的目的就是让刷脏页的频率能赶上当前数据库的负载情况。自适应刷脏页会自动判断每秒应该刷多少脏页。

在mysql内部测试中发现,自适应刷脏页并不是在所有场景中都有性能提升,但是在redo log快满的时候,有较大的效果

 

Sharp checkpoints,在innodb想reuse一个log file时触发,会产生大量的redo条目,这些redo需要写到redolog中。logfile中之前的redo会被清空,当redo满后就会触发Sharp checkpoints,即时没有达到innodb_max_dirty_pages_pct的值。

 

innodb_adaptive_flushing

开启自适应刷脏页,默认开启。

innodb_adaptive_flushing_lwm

是redo log的最低水位(low water mark),当达到这个值,即时innodb_adaptive_flushing是关闭的,也会触发自适应刷脏页

innodb_flushing_avg_loops

保留之前flush动作的资源快照信息。innodb_flushing_avg_loops越高,说明保留的计算资源时间越长,自适应刷脏页也就越慢

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liuzhilongDBA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值