MySQL -update语句流程总结

4,587 阅读3分钟

废话不多说先来张图解释

update T set value = value+1 where ID =2

我想可能大部分人看完这图,思考片刻,接下来的就不需要在继续看了,但是考虑到部分朋友还是新手(包括自己)以及后面复习,还是稍微唠叨一段。

update过程

首先,上图中深色背景的表示在执行器中执行,也就是Server层,浅色的是在InnoDB引擎中执行。
由于很多朋友并不是专业的DBA或者对MySQL内部原理并不是特别清晰,所以先对redologbinlog做简单的介绍。

  • redolog

    重做日志,属于物理日志,上面存储的是数据库中最终的内容,有固定的大小,可以循环读写,一般设置innodb_flush_log_at_trx_commit为1,表示commit事务时将redolog上面的数据刷入到磁盘(具体的可以自行研究redolog file 和redolog buffer)。具有两个状态分别是preparecommit,在MySQL重启恢复时会根据commit状态恢复数据。

  • binlog

    归档日志,属于逻辑日志,上面存储的是最初的修改逻辑可以简单的理解为sql语句,可以追加写,一般设置sync_binlog为1,表示commit事务时将binlog上面的数据刷入到磁盘进行归档。数据恢复和同步都是通过binlog来实现的。

下面以文字的方式再次描述一下update T set value = value+1 where ID =2的过程。

  1. 词法分析器识别出事update语句;
  2. 执行器去InnoDB中进行查询,找到满足ID = 2 的数据;
  3. 执行器将value的值加1;
  4. 执行器让InnoDB将刚刚的新值写入到InnoDB的内存中;
  5. InnoDB在redolog中加入一条记录,并把该记录的状态设置为prepare;
  6. 执行器经“update T set value = value+1 where ID =2” 写入到binlog中;
  7. 此时提交事务,将redolog中prepare的的记录状态设为commit,并且将内存中的新数据刷入磁盘。

以上就是比较简单的过程理解,那么为啥要分开写redolog呢?即传说中的两阶段提交?这里再做个简单的分析。

首先对这种方式的好处做个总结:保证以上所有的过程如果出现MySQL实例奔溃都不会导致事务的丢失或异常。

接下来分析一下这么做的具体原因:

  1. 如果是第5步之前crash,就是还没写任何日志,那么事务就不存在,在恢复后从redolog和binlog中都不会有任何的问题;
  2. 如果写完redolog 的prepare出现了crash,那么恢复时,通过redolog和binlog的对比,会发现只要一个prepare的日志,那么会将事务进行回滚,保证redolog和binlog的统一;
  3. 如果写完binlog后出现crash,那么恢复时,会进行根据binlog日志对redolog进行补偿,对redolog之前prepare的记录修改为commit状态,事务得到保证;
  4. 最后commit后crash,redolog和binlog都是正常的。

redolog只出现在InnDB中,而且是循环写的,不能持久保存,所以暂时不能用redolog来做主从或者数据备份

以上的是总结了很多博客和书上的内容,并不是完全的原创,自己也是在整理,希望大家能指正不对之处。