转载

mysql sync_binlog和 innodb_flush_log_at_trx_commit

今天聊一聊关于mysql innodb存储引擎中一个事务的完整流程:
首先说下innodb的事务日志概念:
ib_logfile文件就是innodb的事务日志,可以理解是INNODB的REDO日志,当数据库异常关闭的时候,innodb存储引擎下的mysql借助事务日志来完成实例恢复,即前滚和回滚来保证数据库一致性;
区别于binlog日志又叫二进制日志文件,它会将mysql中所有修改数据库数据的Query以二进制的形式记录到日志文件中,如:create,insert,drop,update等;(对于select操作则不会被记录到binlog里,因为它并没有修改数据库的数据),binlog主要是用于保证数据完整的,如主从备份,通过从binlog文件中读取操作Query来在salve机上进行同样的操作,保证主从同步,同时也可以作为恢复数据的工具。
Innodb还有另外一个日志Undo log,但Undo log是存放在共享表空间里面的(ibdata*文件,存储的是check point日志序列号)。
InnoDB 日志缓冲区(InnoDB Log Buffer):这是 InnoDB 存储引擎的事务日志所使用的缓冲区。类似于 Binlog Buffer,InnoDB 在写事务日志的时候,为了提高性能,也是先将信息写入 Innofb Log Buffer 中,当满足 innodb_flush_log_trx_commit 参数所设置的相应条件(或者日志缓冲区写满)之后,才会将日志写到文件(或者同步到磁盘)中。可以通过 innodb_log_buffer_size 参数设置其可以使用的最大内存空间;
下面重点讲解 innodb_flush_log_trx_commit 参数:下图可以清楚的展现出该参数设置成不同值时log刷新的不同过程;
mysql sync_binlog和 innodb_flush_log_at_trx_commit
针对这张图第一个箭头代表着每次commit的时候,事务日志到达的地方, 然后第二个箭头,代表刷新到磁盘永久保存的过程, 后面的fsync every commit、fsync every second 、fsync every second 是在分别形容第二个箭头刷新的条件。
然后还需要注意的:宏观上写进logfile就是写进磁盘了。但是微观上写进logfile是先写进了os cahce,然后再刷新到raid cache(前提是做了raid)最后到磁盘。
具体分析innodb_flush_log_at_trx_commit=N的意义:
innodb_flush_log_at_trx_commit=0,每次commit时,事务日志写进了innodb log buffer ,然后每秒Log Thread 会将事务日志从innodb log buffer刷新到ib_ogfile(也就刷新到了磁盘)。当innodb_flush_log_at_trx_commit设置为0,mysqld进程的崩溃会导致上一秒钟所有事务数据的丢失,这是因为每次commit,事务日志只是写进了innodb log buffer 中,然后是每秒才将innodb log buffer 中的事务日志刷新到磁盘永久保存,所以mysqld进程的崩溃时,innodb log buffer可能会有一秒的日志没有刷新出来,但是在这种情况下,MySQL性能最好
innodb_flush_log_at_trx_commit=2,每次commit时,事务日志写进了innodb log buffer,并同时接着写进os cache, 也就是说每次commit,事务日志写进了os cache中, 然后每秒从os cache刷新到ib_logfile(也就是刷新到了磁盘)。当innodb_flush_log_at_trx_commit设置为2,只有在操作系统崩溃或者系统掉电的情况下,上一秒钟所有事务数据才可能丢失,因为每次commit,事务日志已经进入了os cache,所以mysqld崩溃,事务日志是不会丢失的;
innodb_flush_log_at_trx_commit设置为1,这是最安全的设置,同时由于频繁的io操作,导致效率是最差的,这时候不管是mysqld,还是操作系统崩溃,都不会丢数据,这是因为每次commit,事务日志都刷新到了磁盘永久保存了;
选取的原则:
对于一些数据一致性和完整性要求不高的应用,配置为 2 就足够了;如果为了最高性能,可以设置为 0。有些应用,如支付服务,对一致性和完整性要求很高,所以即使最慢,也最好设置为 1.。
然后介绍参数sync_binlog :
sync_binlog =  N: 控制的是从binlog buffer中刷新binlog到底层binlog文件(也就是刷新到底层磁盘)
N>0    每向二进制日志文件写入N条SQL或N个事务后,则把二进制日志文件的数据刷新到磁盘上; 
N=0    不主动刷新二进制日志文件的数据到磁盘上,而是由操作系统决定; 
推荐配置组合: 
1)innodb_flush_log_at_trx_commit=1同时sync_binlog =1
这就是所谓的双1设置:这种配置适合数据安全性要求非常高,而且磁盘IO写能力足够支持业务,比如充值消费系统,银行业务; 
2)innodb_flush_log_at_trx_commit=1同时sync_binlog =0
这种设置:保证了事务日志是全的,也就保证可以实例恢复,即前滚和回滚,适合数据安全性要求高,磁盘IO写能力不太富余;
3))innodb_flush_log_at_trx_commit=2或者0同时sync_binlog =2或者m(0<m<100) </m<100)<>
这种设置:适合数据安全性有要求,允许丢失一点事务日志;
4)innodb_flush_log_at_trx_commit=0同时sync_binlog =0
这种配置适合 :磁盘IO写能力有限,对数据安全要求较低,例如:日志性登记业务; 
总结:通过对innodb_flush_log_at_trx_commit参数的学习,我知道了mysql在刷新事务日志的时候,还会经历os cache这个过程,并且双1设置可以实现很高的一致性需求;
正文到此结束
Loading...