From 22bf36ef4794dbe0ad8ac9a3388b9fbb410db214 Mon Sep 17 00:00:00 2001 From: asahi Date: Mon, 4 Nov 2024 20:49:56 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=85=E8=AF=BBmysql=20innodb=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mysql/mysql文档/undo log.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/mysql/mysql文档/undo log.md b/mysql/mysql文档/undo log.md index cc5af0e..f4ec78a 100644 --- a/mysql/mysql文档/undo log.md +++ b/mysql/mysql文档/undo log.md @@ -1 +1,29 @@ # innodb存储引擎 +## innodb多版本控制 +innodb是一个多版本存储引擎,innodb针对被修改的数据行(changed rows)保存了旧版本信息,故而其支持并发、回滚等事务特性。旧版本信息存储在undo tablespaces中,按rollback segment的结构进行存储。在事务回滚时,innodb会使用rollback segment中存储的信息来执行undo操作。 + +同样的,innodb也会使用rollback segment中的信息来构建更早的行数据的版本,从而保证读操作的一致性。 + +innodb会在内部为存储在数据库中的每行数据新增3个字段: +- `DB_TRX`: 该字段为6字节,代表能唯一标识`最后更新或插入(insert/update)该行数据的事务`的标识id。并且,在内部`delete操作也被视为update操作`,在删除数据时,行数据中特定位置的bit会被置位,将该行数据标识为删除 +- `DB_ROLL_PTR`: 该字段为7字节,被称为roll pointer。roll pointer指向一条写入到rollback sengment中的undo log记录,如果当前行被更新,那么undo log中包含可以重新构建行数据中更新前版本的信息。 +- `DB_ROLL_ID`:该字段为6字节,该字段随着新数据被插入而单调增加。如果innodb自动产生了聚簇索引,那么索引中将会包含row id的值;否则`DB_ROW_ID`将不会出现在任何索引中 + +rollback segment中的undo logs被区分为了insert和update类型。 +- insert undo log只在事务回滚时才需要,并且在事务提交之后就被丢弃 +- update undo log除了在事务回滚时需要用到外,在一致性读操作中也需要用到。innodb为一致性读分配了一个事务的快照,只有当快照中的事务都不存在后,update undo log才能被丢弃。在保证一致性读时,可能需要undo log中的信息来构建行数据修改前的早期版本。 + +`建议定期提交事务,即使是只进行一致性读的事务`。否则,在事务提交前,innodb无法丢弃update undo log,rollback segment占用空间大小会快速增加,填满其所在的undo tablespace。 + +rollback segment中的undo log record,其占用物理空间大小通常小于关联的插入或更新行,可以通过该信息来计算rollback segment所需要的空间。 + +在innodb的多版本控制方案中,在通过sql语句删除行数据时,行数据并不会马上从数据库中被移除。只有该删除操作关联的update undo log record被丢弃时,行数据和其关联索引记录才会被物理移除。该移除操作称之为purge,移除操作的发生顺序和sql语句的执行时间顺序相同。 + +### 多版本和辅助索引 +innodb mvcc将聚簇索引和非聚簇索引分开对待。聚簇索引中的记录会就地更新,并且其隐藏的系统列会指向undo log record。不像聚簇索引记录,非聚簇索引记录并不会包含隐藏的系统列,也不会就地更新。 + +当非聚簇索引列被更新时,旧的聚簇索引记录将会被标记为删除,新记录将会被插入,并且标记为删除的索引记录将会被purge。当非聚簇索引记录被标记为删除或非聚簇索引page被新事务更新,innodb会在聚簇索引中查找数据记录。在聚簇索引中,如果记录在读取事务初始化之后被更新,那么记录的`DB_TRX`将会被检查,并且会从undo log中获取正确的版本号。 + + + +