前言
双1是什么?
即:参数 innodb_flush_log_at_trx_commit 和sync_binlog均设置为1。
接下来,先看由该参数引起的一个案例。
案例
场景:
mysql 故障宕机,查看binlog的最后一个事务,如下:
'/*!*/;### INSERT INTO `guolm`.`t1`### SET### @1=806527 /* INT meta=0 nullable=0 is_null=0 */### @2='n806527' /* VARSTRING(80) meta=80 nullable=1 is_null=0 */# at 6822647#180425 18:00:49 server id 6451 end_log_pos 6822678 CRC32 0x05e6ff87 Xid = 1175295COMMIT/*!*/;
在启动mysql之后,查看最后一个事务在表中不存在:
mysql> select * from guolm.t1 where id=806527;Empty set (0.00 sec)
原因:
innodb_flush_log_at_trx_commit = 0
可能在mysql突然宕机时,脏页没有来得及刷新到磁盘,而因为该参数设置的不是及时将redo log刷新到磁盘,所以有一部分redo log没有保存到磁盘,
故在mysql启动时,由于丢失了部分redo log,并且脏页部分没有刷到磁盘,因此丢失了那些已经提交的事务。
思考
在遇到意外宕机时:
若 innodb_flush_log_at_trx_commit 设置的是0:
- 将不能够及时的将redo log 刷新到磁盘。
- 若意外宕机,redo log没有刷到盘里,在启动时,可能会造成部分事务丢失,提交的数据缺少。
- 在线上使用中,即使担心刷盘频繁,也要最低是为2,不要设置为0
若 sync_binlog 设置的是0:
- 将不能及时将binlog及时刷新到磁盘。
- 在需要根据binlog找position/gtid/Xid的情况下,无法获取最后一个事务的position/gtid/Xid,因为可能部分binlog没有保存到文件中,所以丢失了一些binlog日志。
附录
innodb_flush_log_at_trx_commit —— 将redo log同步到磁盘的策略
- 0:当事务提交时,不刷新日志到磁盘,而是等待主线程每秒刷新重做日志。
- 1:在commit时,将重做日志缓冲同步到磁盘中。
- 2:在commit时,将重做日志缓冲异步到磁盘中,即重做日志会先同步到操作系统的文件系统缓存中,就提示提交完成,后来在异步写入磁盘。
sync_binlog —— 将binlog同步到磁盘的策略
- 0:当事务提交之后,MySQL不对binlog_cache做fsync同步磁盘,由操作系统决定什么时候刷到磁盘。
- 1:在事务提交时,便将binlog刷到磁盘文件中。