mysql> update T set c=c+1 where ID=2;
复制代码
日志
redo log(重做日志)
为了解决每次更新,都要将对应的更新操作写进磁盘,来提升更新效率。
并能保证数据库发生异常重启,之前提交的数据不会丢失 —— crash-safe;
InnoDB 的 redo log 大小是固定的,其数据结构类似与循环队列。
一条记录更新时,InnoDB引擎会把记录先写道 redo log,并更新缓存,这样就算完成了一次更新。Inno DB引擎会在适当的时候去更新到磁盘中,通常是在系统空闲的时候。
如果 redo log 写满,则 InnoDB 需要先将一部分数据更新到磁盘,以腾出 redo log 的空间。
binlog(归档日志)
同redo log的不同:
- redo log 是 InnoDB 引擎特有的;binlog 是 MySQL的 Server 层实现,所有引擎都可使用。
- redo log 是物理日志,记录的是在某个数据页上做了什么修改;binlog 是逻辑日志,记录的是这个日志的原始逻辑,如果给ID=2的c字段加1
- redo log 是循环写,binlog是追加写
更新过程
然后在看一下,InnoDB 在执行上边 sql 语句的内部更新过程:
- 执行器先找引擎取ID=2的这一行记录。如果该行记录的数据页本来就在内存中,就直接返回给执行器;否则就从磁盘读入内存,然后在返回。
- 执行器拿到引擎给的行数据,把值加1,得到新的一行数据,在调用引擎接口写入这行新记录。
- 引擎将这行新记录更新到内存中,同时将这个新记录记录到 redo log,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
- 执行器生生这个操作的binlog,并把binlog写入磁盘。
- 执行器调用引擎的提交事务接口,引擎把刚刚写入的 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。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END