30 lines
3.3 KiB
Markdown
30 lines
3.3 KiB
Markdown
# 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中获取正确的版本号。
|
||
|
||
|
||
|
||
|