日志系统:SQL的更新过程

image.png

mysql> update T set c=c+1 where ID=2;
复制代码

日志

redo log(重做日志)

为了解决每次更新,都要将对应的更新操作写进磁盘,来提升更新效率。
并能保证数据库发生异常重启,之前提交的数据不会丢失 —— crash-safe;

image.png
InnoDB 的 redo log 大小是固定的,其数据结构类似与循环队列。

一条记录更新时,InnoDB引擎会把记录先写道 redo log,并更新缓存,这样就算完成了一次更新。Inno DB引擎会在适当的时候去更新到磁盘中,通常是在系统空闲的时候。
如果 redo log 写满,则 InnoDB 需要先将一部分数据更新到磁盘,以腾出 redo log 的空间。

binlog(归档日志)

同redo log的不同:

  1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL的 Server 层实现,所有引擎都可使用。
  2. redo log 是物理日志,记录的是在某个数据页上做了什么修改;binlog 是逻辑日志,记录的是这个日志的原始逻辑,如果给ID=2的c字段加1
  3. redo log 是循环写,binlog是追加写

更新过程

image.png

然后在看一下,InnoDB 在执行上边 sql 语句的内部更新过程:

  1. 执行器先找引擎取ID=2的这一行记录。如果该行记录的数据页本来就在内存中,就直接返回给执行器;否则就从磁盘读入内存,然后在返回。
  2. 执行器拿到引擎给的行数据,把值加1,得到新的一行数据,在调用引擎接口写入这行新记录。
  3. 引擎将这行新记录更新到内存中,同时将这个新记录记录到 redo log,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
  4. 执行器生生这个操作的binlog,并把binlog写入磁盘。
  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

两阶段提交

为什么有两阶段提交?
为的是保证两份日志之间的逻辑一致。

如果不用两阶段提交,如先写 redo log 后写 binlog。当redo log 写完,binlog 未写完,MySQL发生异常重启。此时 binlog 中丢失了该条语句的记录,如果以 binlog 进行数据恢复,会导致丢失了一条更新。反之,如果先写 binlog 后写 redo log ,则会多一条更新。

redo log 和 binlog 的更新频率

innodb_flush_log_at_trx_commit
sync_binlog
为了不丢失日志,都建议设置为1。

参考:MySQL参数:innodb_flush_log_at_trx_commit 和 sync_binlog

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享