redo log
redo log即重做日志文件,用于记录事物操作的变化,记录的是数据修改后的值,不管事务是否提交都会记录下来,保证数据的完整性
redo log写的方式:
- 顺序写—第一个文件写满之后,会按顺序写下一个文件
- 循环写—写满最后一个文件之后,会重新从都一个文件开始写
写满日志文件会产生切换操作,并执行checkpoint,触发脏页刷新。
当mysql数据库重启时,如果参数文件的redo log值与当前redo log值不一致,会把现有的redo log删除,并按照参数文件设置的大小重新生成redo log文件。在此之前,数据会先写入 redo log buffer
redo log buffer刷到磁盘的条件:
- innodb_flush_log_at_trx_commit参数:
- 0—性能最好,不太安全—每次事务提交不会触发redo log thread将日志缓冲中的数据写入 redo log 文件
- 1—安全,但是数据库性能慢—每次事务提交时,触发redo log thread将日志缓冲中的数据写入 redo log 文件,并flush到磁盘
- 2—中规中矩—每次事务提交时,触发redo log thread将日志缓冲中的数据写入 redo log 文件,但不会刷新(flush)到磁盘,该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操作。
- master thread:每秒进行刷新
- redo log buffer:使用超过一半的时候会触发刷新
binlog
mysql的二进制日志文件,以二进制方式记录了数据库上的所有改变,用于备份恢复和主从备份。
binlog cache刷新到磁盘的binlog文件的条件为sync_binlog参数,该参数有n个值:
- 0:事务提交之后,mysql不做fsync之类的 磁盘同步指令 刷新binlog cache中的信息到硬盘,而是让 filesystem自行决定什么时候来做同步,或cache满了之后才同步到硬盘
- n:每进行n此事务提交之后,mysql将进行一次 fsync之类的 磁盘同步指令 将binlog cache中的信息强制写入到硬盘
- 为了安全性设置为1,最佳性能设置为0
- 双一模式:sync_binlog=1,innodb_flush_log_at_trx_commit=1。即:每次事务提交之后,mysql会进行一次 fsync之类的 磁盘同步指令 将binlog cache中的信息强制写入到硬盘,且触发redo log thread将日志缓冲中的数据写入 redo log 文件,并flush到磁盘
binlog和redo log异同
- 记录内容不同
- binlog是逻辑日志,记录所有数据的改变信息
- redo log是物理日志,记录所有InnoDB表数据的变化
- 记录内容的时间不同
- binlog记录commit完毕之后的DML和DDL SQL语句
- redo log记录事务发起之后的DML和DDL SQL语句
- 文件使用方式的不同
- binlog不是循环使用,在写满或者实例重启之后,会生成新的binlog文件
- redo log是循环使用,最后一个文件写满之后,会重新写第一个文件
- 作用不同
- 准备阶段(transaction prepare):事务语句先写入redo log buffer,然后做一个事务准备标记,再将log buffer中的数据刷新到redo log
- 提交阶段(commit):将事务产生的biglog写入文件,刷入磁盘
只要binlog写入完成,在主从环境中,都会正常完成事务
一条update语句的执行过程(update T set c=c+1 where ID=2;
):
脏页刷新条件
- 重做日志ib_logfile文件写满之后,在切换的过程中会执行checkpoint,会触发脏页的刷新条件
- 通过innodb_max_dirty_pages_pct参数的值控制。该参数是指在buffer pool中dirty page所占的百分比,达到设置的值,就会触发脏页的刷新
- 由innodb_adaptive_flushing参数控制。该参数影响每秒刷新脏页的数目。
- 刷新流程:
- InnoDB的 redo log是固定大小的,比如可以配置一组4个文件,每个文件大小是1GB,那么这个redo log就可以记录4GB的操作。从头开始写,写到末尾又回到开头循环写:
- write pos 是当前记录的位置,一边写一边后移,写到三号文件末尾后就回到0号文件开头
- checkpoint是当前要擦除的位置,也是往后推移且循环的,擦除记录前要把记录更新到数据文件
- 上面二者之间的部分是用来记录新操作的空间,如果write pos追上checkpoint,此时不能再执行新的更新,需要先停止并擦除一些记录