Mysql的多种日志


总结一下binlog undolog redolog

分类

从大的方向来,binlog也就是二进制日志,是为了保证数据库的数据持久化的,而undolog 和redolog是数据库事务中保证事务的ACID的两个日志,然后就分开说:

一条sql语句的执行链路

例如一条更新语句,执行链路如下

  1. 如果buffer pool中没有对应的数据, 从磁盘加载这条数据
  2. 如果内存中没有数据,从磁盘加载后,记录一个undo log。直接写入磁盘,记录更新前的数据
  3. 更新内存中的数据
  4. 写redo log日志到内存
  5. 将redo log写入磁盘 prepare阶段
  6. 准备提交事物,将binlog文件写入磁盘
  7. 将修改的binlog文件名和修改的位置记录到redolog中,最后加入commit标记,commit标记表示此次事物成功提交了,除此之外都不算成功
  8. 会有一个后台线程,定时将内存数据写入磁盘。同时删除对应redolog

Binlog

二进制日志包含了引起或可能引起数据库改变(如delete)的事件信息,但不包含例如select和show这样的查询语句.以事件的形式保存,包含了时间,时间开始和结束的位置等信息.
二进制日志是以事件形式记录的,所以对于事务的操作,二进制日志只在事务提交的时候一次性写入,对于非事务表的操作,执行完就直接写入.

开启

Mysql默认没有启动二进制日志,通过--log-bin=[on|off|filename]开启,或者通过修改my.ini文件.

作用

二进制日志的作用就是为了定点恢复数据库和主从复制的时候使用.

  • 定点还原
    可以选择基于时间点和位置的恢复,通过mysqlbinlog命令
  • 主从复制
    主从复制是基于3个线程的交互:
  1. Master上面的binlog dump线程,负责将master的binlog event传到slave
  2. Slave上面的IO线程,负责接收Master传过来的binlog,并写入relay log
  3. slave上面的sql线程,读取relay log并执行

redo log , undo log

之前说了,redo undo是在数据库事务中为了保证ACID而存在的,隔离性是由锁实现的,持久性通过redo实现,原子性和一致性通过undo log实现.仔细说说

redo log

一般事务开始的时候就会产生redo_log,redo_log并不是随着事务的提交写入,而是在事务的执行过程中就写入,就是为了防止故障发生的时候,还有未写入磁盘的脏页数据,如果发生故障,会在重启mysql的时候,根据redo log进行重做.当事务的脏页数据写入磁盘后,redo_log的空间就会被覆盖.

undo log

保存事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读.
在事务开始前生成undo log,同时undo也会产生redo保证undo log的可靠性,当事务提交后,undo并不能立马删除,而是放入待清理的链表,由purge线程判断是否由其他事务在使用undo段中表的上一个事务之前的版本信息,决定是否可以清理undo log的日志空间.

MVCC

多版本并发控制,这是一个无锁的并发控制方法,从大的方向来看,就是通过某种方法实现让连接到数据库的瞬间看到数据库的一个快照,写操作完成之前对于其他用户是不可见的.那么重点就是这个某种方法.
当一个MVCC数据库乣更新一条数据的时候,并不是直接用新数据覆盖旧数据,而是将旧数据标记为过时,并在别处增加新版本的数据,这样就会有存储多个版本的数据,但是只有一个是最新的.总之,MVCC就是同一份数据临时保留多版本的一种方式,进而实现并发控制.然后就是实现了.

MVCC插入

当我们建表时,每个表都有三列隐藏记录,和MVCC有关系的就是DB_TRX_ID(数据行版本号)和DB_ROLL_PT(删除版本号),当我们插入数据时,会将事务ID记录到DB_TRX_ID中.

MVCC删除

同样的,当我们删除时,也会将全局事务ID记录到DB_ROLL_PL

MVCC修改

当我们修改数据的时候,会先复制一条当前记录行数据,同事标记这条数据的数据行版本号为当前事务版本号,最后把原来数据行的删除版本号标记为当前事务.

MVCC查询

  • 查找数据行版本号早于当前事务版本号的数据行记录
    也就是说,数据行的版本号要小于或等于当前事务的系统版本号,这样也就确保读取到的数据时事务开始前已经存在的数据
  • 查找删除版本号要么为null,要么大于当前事务版本号的记录
    这样才能确保查询出来的数据在事务开启之前没有被删除

总结

整体看下来并不复杂,就是通过两个版本号来保证读取和写入的时间合理性.MVCC用在数据库事务的RC隔离性中,我们知道RC保证了不发生脏读,当发生写操作的时候通过排它锁,而读操作就是MVCC,因为MVCC可以读取到被锁住的数据的其他版本,并发量就up了


  目录