MySQL的几种日志

每一个操作在真正写入数据库之前,都会先写入日志。MySQL的日志主要包括 错误日志、查询日志、慢查询日志、事务日志、二进制日志 等几大类。

二进制日志binlog

  1. binlog记录写入性操作(不包含查询)信息
  2. 以二进制形式保存在磁盘中
  3. binlog是由Server层进行记录的,使用任何存储引擎的MySQL数据库均会记录binlog日志
  4. binlog是以追加的方式进行写入的
  5. 可以通过设置max_binlog_size参数来设置每个binlog文件的大小
  6. binlog的三个主要使用场景:(1)主从复制(2)数据恢复(3)信息审计
  7. 对于InnoDB存储引擎来说,只有事务提交时才会记录binlog
  8. binlog的刷盘时机,通过sync_binlog参数来进行控制
  9. binlog的日志三种格式:statement、row(默认)和mixed,通过binlog-format参数指定。statement格式会记录修改sql语句, row格式会记录行的数据内容变更,记两条,更新前和更新后都有。

事务日志redo log和undo log

redo log

  1. redo log包含两部分,一个是内存中的日志缓冲(redo log buffer,临时的),另一个是磁盘上的日志文件(redo log file,持久的)
  2. mysql每执行一条DML语句,会先将记录写入redo log buffer,后续某个时间点再一次性将多个操作记录写到redo log file。这种先写日志再写磁盘的技术,就是MySQL里经常说到的WAL(Write-Ahead Logging)技术
  3. redo log buffer写入redo log file实际上是先写入OS Buffer,然后再通过系统调用fsync()将其刷到redo log file中
  4. mysql支持3种将redo log buffer写入redo log file的时机,可以通过innodb_flush_log_at_trx_commit参数进行配置
  5. redo log实现上采用了大小固定,循环写入的方式,当写到结尾时,会回到开头循环写日志。在系统启动的时候,就已经为redo log分配了一块连续的存储空间,以顺序追加的方式记录redo log,通过顺序IO来改善性能。所有的事务共享redo log的存储空间,它们的redo Log按语句的执行顺序,依次交替的记录在一起。
  6. 只依靠binlog是没有crash-safe能力的,只有redo log也不行。因为redo log是InnoDB特有的,且日志上的记录落盘后会被覆盖掉。因此需要binlog和redo log二者同时记录,才能保证当数据库发生宕机重启时,数据不会丢失
  7. 如果数据库崩溃或者宕机,那么当系统重启进行恢复时,可以根据redo log中记录的日志,把数据库恢复到崩溃前的一个状态。未完成的事务可以继续提交,也可以选择回滚,这基于恢复的策略而定。
  8. redo log是innodb独有的,binlog是所有引擎都可以使用的
  9. redo log是循环写的,空间会用完,binlog是可以追加写的,不会覆盖之前的日志信息
  10. binlog和redo log必须保持一致,不允许出现binlog有记录但redo log没有的情况,反之亦然

##undo log

  1. 数据库事务的原子性保证,底层就是通过undo log实现的,主要用作回滚
  2. undo log主要记录了数据的逻辑变化。比如一条INSERT语句,对应一条DELETE的undo log;对于每个UPDATE语句,对应一条相反的UPDATE的undo log。这样在发生错误时,就能回滚到事务之前的数据状态
  3. undo log也是MVCC(多版本并发控制)实现的关键
  4. Innodb通过force log at commit机制实现事务的持久性。即在事务提交的时候,必须先将该事务的所有事务日志写入到磁盘上的redo log file和undo log file中进行持久化。为了确保每次日志都能写入到事务日志文件中,在每次将log buffer中的日志写入日志文件的过程中都会调用一次操作系统的fsync操作(fsync函数同步内存中所有已修改的文件数据到储存设备)
  5. 单个事务的回滚,只会回滚当前事务做的操作,并不会影响到其他的事务做的操作。
  6. redo log保证的是事务的持久性和一致性,而undo log则保证了事务的原子性