事务启动方式
1.第一种启动方式,begin/start transaction 命令不是一个事务的起点,在执行它们之后的第一个操作InnoDB表的语句,事务才是真正的启动。
2.第二种启动方式,一致性视图是在执行 start transaction with consistent snapshot 时创建的。start transaction with consistent snapshot 是马上启动事务。
注:所有的增删改查都会生成一致性视图。
视图概念
1.普通视图,view。它是一个查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果。
语法:CREATE VIEW 视图名 AS SELECT 查询语句。
2.InnoDB在实现MVCC时用到的一致性读视图,consistent read view。用于支持RC(read committed, 读提交) 和 RR(repeatable read, 可重复读)隔离级别的实现。
MVCC原理
InnoDB 每个事务都有一个唯一的事务ID,叫做 transaction id。事务id是在事务开始的时候向InnoDB 的事务系统申请的,是按申请顺序严格递增的。
版本链
对于使用InnoDB存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们创建的表中有主键或者非NULL的UNIQUE键时都不会包含row_id列)
trx_id:每次事务更新数据时,都会生成一个新的数据版本,都会把 transaction id 赋值给 trx_id 隐藏列。旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到他。
roll_pointer:每次事务更新数据时,会把旧的版本写入到undo log日志中,然后这个隐藏列就相当于一个指针,可以通过它找到该记录修改前的信息。
也就是说,数据表中一行数据记录,其实可能有多个版本,每个版本都有自己的row trx_id。
![](https://img.haomeiwen.com/i14016645/c5222f2c8776c422.png)
图中V1至V4是4个版本, 当前最新版本是V4,K的值是22,它是被transaction id 为 25 的事务更新的, 因此它的trx_id也是25。
语句操作数据更新时会生成undo log(回滚日志),而V1, V2, V3 并不是物理上真是存在的,而是每次需要的时候根据当前版本和undo log 计算出来的。每条回滚日志都有roll_pointer 属性(insert 操作对应的undo log 没有该属性, 因为该记录没有更早的版本), 可以将这个undo 日志都连起来, 串成一个链表。
![](https://img.haomeiwen.com/i14016645/65497d1f8d286209.png)
对该记录每次更新后,都会将旧值放到一条undo log 日志中,就算是该记录的一个旧版本,随着更新次数的增多,所有的版本都会被 roll_pointer 属性连成一个链表, 这个链表成为版本链, 版本链头部节点则是当前记录的最新值。如果需要进行找到回滚的undo log,则通过版本链进行一个个的查找, 直到找到目的版本。
注:这也就是为何避免大事务的原因,可能会导致undo增大。
一致性视图
一个事务启动的时候,能够看到所有已经提交的事务。但是之后,这个事务执行期间,其他事物的更新对他不可见。因此一个事务只需要在启动的时候说, 以我启动的时刻为准,如果一个数据版本在我启动之前生成的,就是可见的,如果在启动以后生成的,就是不可见,我必须找到他的上一个版本。如果上一个版本还是不可见的,就继续往上找。如果说是我自己更新的数据,在此是可见的。
网友评论