RedoLog 写入机制
redo log buffer 是全局共用的,中间有生成的日志可以写到 redo log buffer 中。redo log buffer 中的内容还能“搭便车”,其他事务提交的时候可以被一起写到磁盘中。
redo log 的写入策略,由innodb_flush_log_at_trx_commit 参数控制。
设置为 0 表示每次事务提交时都只是把 redo log 留在 redo log buffer 中 ;
设置为 1 的时候,表示每次事务提交时都将 redo log 直接持久化到磁盘;
设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 page cache。
注:(InnoDB 有一个后台线程,每隔 1 秒就会把 redo log buffer 中的日志,调用 write 写到文件系统的 page cache,然后调用 fsync 持久化到磁盘。)
BinLog 写入机制
事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 binlog 文件中。
一个事务的 binlog 是不能被拆开的、或者“被打断的”,因此不论这个事务多大,也要确保一次性写入。
所以系统给 binlog cache 分配了一片内存每个线程一个,参数 binlog_cache_size 用于控制单个线程内 binlog cache 所占内存的大小。
如果超过了这个参数规定的大小,就要暂存到磁盘。
write 和 fsync 的时机,是由参数 sync_binlog 控制的:
sync_binlog=0 的时候,表示每次提交事务都只 write,不 fsync;
sync_binlog=1 的时候,表示每次提交事务都会执行 fsync;
sync_binlog=N(N>1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才 fsync。
日志安全模式
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1。
双1配置下不会丢失任何数据,也就意味一个事务完整提交前,需要等待两次刷盘,
一次是 redo log(prepare 阶段),一次是 binlog。
组提交
为了在保证数据的完整性很多系统都配置为双1配置,特别是结算、财务类
此配置下写入的性能就会有一定的下降
虽然redo、binlog都是顺序写,但是数据页的修改是IO的随机磁盘操作
所以为了尽大可能的减少IO的操作诞生了group commit机制。
image.png
trx1 是第一个到达的,会被选为这组的 leader;
等 trx1 要开始写盘的时候,这个组里面已经有了三个事务,这时候 LSN 也变成了 150;
trx1 去写盘的时候,带的就是 LSN=150,因此等 trx1 返回时,所有 LSN 小于等于 160 的 redo log,都已经被持久化到磁盘;
这时候 trx2 和 trx3 就可以直接返回了。
所以,一次组提交里面,组员越多,节约磁盘 IOPS 的效果越好。
在并发更新场景下,第一个事务写完 redo log buffer 以后,接下来这个 fsync 越晚调用,组员可能越多,节约 IOPS 的效果就越好。
参数配置
binlog_group_commit_sync_delay
表示延迟多少微秒后才调用 fsync
binlog_group_commit_sync_no_delay_count
表示累积多少次以后才调用 fsync
这两个条件是或的关系,也就是说只要有一个满足条件就会调用 fsync。
所以,当 binlog_group_commit_sync_delay 设置为 0 的时候,binlog_group_commit_sync_no_delay_count 也无效了。
相关
innodb double write
double write是由2部分组成,一部分是内存中的double write buffer(2M),另外一部分是共享表空间2个区,128个页组成,同样也是2M。
当缓冲池刷脏的时候并不直接写磁盘,而是拷贝内存中的脏数据到内存中的double writer buffer之后分为2次,每次写入1M到共享表空间的物理磁盘上,然后调用fsync同步到磁盘,完成double writer buffer写入之后再写入到各个表空间文件中。
change buffer(索引非唯一 、索引为辅助索引)
对于聚簇索引,id自增列,页中的行记录按照ID执行顺序存放,所以不会涉及到其它页的访问,所以一般的插入很快就能完成,但是二级索引的插入则不是有序的,需要离散的访问非聚簇索引页。
所以一般就放在插入缓存中然后再以一定的频率执行插入缓冲和非聚集索引叶子结点的合并操作。