关于MySQL的InnoDB的MVCC原理,很多朋友都能说个大概:
每行记录都含有两个隐藏列,分别是记录的创建时间与删除时间
每次开启事务都会产生一个全局自增ID
在RR隔离级别下
INSERT -> 记录的创建时间 = 当前事务ID,删除时间 = NULL
DELETE -> 记录的创建时间不动,删除时间 = 当前事务ID
UPDATE -> 将记录复制一次
老记录的创建时间不动,删除时间 = 当前事务ID
新记录的创建时间 = 当前事务ID,删除时间 = NULL
SELECT -> 返回的记录需要满足两个条件:
创建时间 <= 当前事务ID (记录是在当前事务之前或者由当前事务创建的)
删除时间 == NULL || 删除时间 > 当前事务ID (记录是在当前事务之后被删除的)
但实际上,这个描述是很不严格的,问题有以下几点:
1. 每条记录含有的隐藏列不是两个而是三个
它们分别是:
DB_TRX_ID, 6byte, 创建这条记录/最后一次更新这条记录的事务ID
DB_ROLL_PTR, 7byte,回滚指针,指向这条记录的上一个版本(存储于rollback segment里)
DB_ROW_ID, 6byte,隐含的自增ID,如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引
2. 记录的历史版本是放在专门的rollback segment里(undo log)
UPDATE非主键语句的