Sunskey

日拱一卒,不期而至

0%

MySQL 保证数据不丢失的秘密

保证数据不丢失的秘密

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的写入机制

img

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。这样做的风险是,主机掉电的时候会丢数据。