保证数据不丢失的秘密
binlog写入机制
binlog写入逻辑:事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog中。
每个线程由自己的binlog cache ,但是共用同一份binlog文件。
write,指的是把日志写入文件系统的page cache,并没有把数据持久化到磁盘,所以速度快。
fsync,将数据持久化到磁盘的操作。
write和fsync的时机,是由参数sync_binlog控制的;
1.sync_binlog = 0的时候,表示每次提交事务都只write,不fsync;
2.sync_binlog =1的时候,表示每次提交事务都会执行fsync;
3.sync_binlog=N(N>1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才 fsync。
redo log的写入机制
1.存在redo log buffer中,物理上是在MySQL进程内存中。
2.写到磁盘(write),但是没有持久化(fsync),物理上文件系统的page cache里面。
3.持久化到磁盘,对应的是hard disk。
InnoDB提供了innodb_flush_log_at_trx_commit参数控制redo log的写入策略。
0:表示每次事务提交时都只是把redo log留在redo log buffer中
1:表示每次事务提交都将redo log持久化硬盘
2:每次提交都只是把redo log写到page cache
InnoDB有一个后台线程,每间隔一秒,就会把redo log buffer中的日志,调用write 写到文件系统的page cache ,然后fsync持久化磁盘。
3种情况会把让没有提交事务的redo log写入到磁盘中
1.后台线程每秒一次的轮询操作。
2.redo log buffer占用的空间即将达到innodb_log_buffer_size一半的时候,后台线程会主动写盘。
3.并行的事务提交的时候,顺带将这个事务的redo log buffer持久化到磁盘。
MySQL的双一配置。指的就是sync_binlog和innodb_flush_log_at_trx_commit都设置成1。一个事务完整提交前,需要等待两次刷盘,一次是redo log(prepare ),一次是binlog.
日志逻辑序列(LSN)是单调递增的,用来对应redo log的一个个写入点。每次写入length的redo log,LSN的值就会加上length。
一次组提交里面,里面的组员越多,节约磁盘IOPS的效果越好。
日志记录过程
如果想binlog提升组提交的效果,可以通过设置binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 来实现。
1.binlog_group_commit_sync_delay参数,表示多少微秒后才调用fsync
2.binlog_group_commit_sync_no_delay_count,表示多少次以后才调用fsync
如果MySQL出现了性能瓶颈,而且瓶颈在IO上
1.通过设置binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count参数你,减少binlog的写盘速度。
2.将sync_binlog设置大于1,这样做的风险是,这个主机掉电会丢失binlog日志。
3.innodb_flush_log_at_trx_commit 设置为 2。这样做的风险是,主机掉电的时候会丢数据。