innodb 什么时候对缓冲区和磁盘中的行数据进行更新?

when does innodb deliver updates to row data in buffer and disk?

我有一个问题,关于 innodb 何时更新缓冲区中的行数据以及更改何时进入磁盘。这个问题来自reading to undo log,它说历史数据在undo log中等待回滚。如果引擎需要undo log 回滚,更新查询的更改必须在提交之前更改行?那么由于数据已经更新,提交会做什么。

当您 INSERTUPDATEDELETE 一行时:

快速总结:

  1. 获取包含该行的块(或应该包含该行的块)。 2. Insert/update/delete 行。
  2. 将块标记为 "dirty"。它最终会被写入磁盘。
  3. 将非唯一二级索引更改放入 "change buffer"

更多详细信息(关于这些步骤):

  1. 要找到 16KB 的块,向下钻取 PRIMARY KEY's BTree。如果该块不在 buffer_pool(分配在 RAM 中)中,则从磁盘中获取它。 (这可能涉及从 buffer_pool.
  2. 中取出其他块
  3. 将之前的值(在 Update/Delete 的情况下)复制到撤消日志,并准备将其刷新到磁盘。
  4. 后台任务将脏页刷新到磁盘。如果一切顺利,buffer_pool 的 'most' 包含非脏页,您 'never' 必须等待 buffer_pool 中的 'free' 块。
  5. Change Buffer 有点像 "delayed write" 用于索引更新。它是透明的。也就是说,后续索引查找将自动在更改缓冲区 and/or 中查找索引的 BTree。 CB中的数据最终会和真正的索引BTree混合,最终刷入磁盘。

UNIQUE 键:所有更改唯一键列的 INSERTsUPDATEs 必须检查重复键而不是通过更改缓冲区。

AUTO_INCREMENT还有一些其他的特殊动作。

根据 innodb_flush_log_at_trx_commitinnodb_doublewrite 的值,某些内容可能会在事务结束时刷新到磁盘。这些处理 "atomic" 交易和 "torn pages".

复制:其他activity可能包括写入和同步二进制日志,以及将数据推送到集群中的其他节点。

设计是 "optimistic",因为它以 ROLLBACK 为代价针对 COMMIT 进行了优化。提交后,一个过程 运行 会清除为防止崩溃和回滚而保留的副本。回滚更复杂,因为它必须放回行的旧副本。 (另见 "history list"。)

搜索我提到的一些关键字;阅读一些其他网页;然后回来提出更具体的问题。

提交

让我们换个角度来看。每行,包括未提交的行 changed/deleted,都有一个 "transaction id"。给定交易的所有行都具有相同的 ID。所以,即使发生崩溃,InnoDB 也知道要清理什么。 COMMITROLLBACK 需要是 'atomic';这是通过一次写入磁盘 "says it all" 来辅助的。唯一可行的方法是将交易 ID 设为关键。请记住,buffer_pool 周围可能散布着一百万行数据文件和日志等待 commit/rollback。

commit/rollback之后,InnoDB 可以悠闲地运行清理周围的东西。例如,在提交或回滚 UPDATE 之前,每行都有两个副本被更改。最终需要删除其中一行。同时,这两行在 "history list" 上。任何其他事务搜索历史列表以查看允许他们查看哪一行——READ UNCOMMITTED = 已提交/回滚的最新行; READ COMMITTED = 提交/回滚的最新行;等等

如果我没理解错的话,undo log是一种优化。例如,在 DELETE 上,"old values" 行被复制到撤消日志,并且该行实际上从数据 BTree 中删除。这里的优化是undo log是串行写入的,而BTree可能会涉及到更多的block,分散在table周围。此外,数据块的正常处理包括将它们缓存在 buffer_pool 中。对于Commit,把undo log中的记录都扔了。对于Rollback,有使用undo log重建的繁琐工作

是的,历史列表会为涉及您最近更改的行的所有其他事务添加工作。但它启用事务隔离模式并有助于从崩溃中恢复。