mysql mvcc知乎_mysql MVCC实现

mysql5.7 关于MVCC的官方文档14.3 InnoDB Multi-Versioning​dev.mysql.com

自己翻译部分需要的信息:

InnoDB是一个多版本存储引擎: 它保存了修改记录的历史版本信息,以便支持事务的并发和回滚功能。这些信息存储在表空间的回滚字段中。InnoDB使用回滚字段中的信息实现事务回滚的取消操作。同时在一致性读中,InnoDB使用这些信息构建了历史版本的记录。

InnoDB在内部给每一条记录添加了三列。一个6字节的事务ID(DB_TRX_ID)表示了上次插入或者更新该条记录的事务识别号。此外,删除操作视为更新操作,用特殊的1位标志符来区分。每条记录还包含一个7字节的回滚指针(DB_ROLL_PTR)。这个回滚指针指向 回滚字段中的一条取消日志记录。如果一条记录遭到了更新,那么取消日志记录中会保存恢复这条记录的所有必要信息(不保存全部信息,个人理解)。一个6字节的记录ID(DB_ROW_ID),随着新纪录的添加而单调增加。(记录ID后续不翻译)

回滚字段中的取消日志 是由 插入取消日志 和 更新取消日志组成的。插入取消日志仅在事务回滚的时候有用。当事务提交的时候,插入取消日志就被销毁。更新取消日志还应用在一致性读中,不同的是,更新取消日志仅在 InnoDB中没有事务的时候才会被销毁,因为InnoDB需要使用更新取消日志为每个事务构建一致性读的快照。(最后一句话,个人理解翻译,建议看原文)

借助于 唐成的数据库多版本的实现https://myslide.cn/slides/3542​myslide.cn

RR 隔离级别下,事务开启的时候,获得当前 未commit的事务ID

RC 隔离级别下,事务每次执行sql的时候,获得当前 未commit的事务ID

一致性读的实现:假设当前事务ID为 TRX_ID_NOW 未提交的所有事务ID为 UNCOMMIT_TRX_ID_LIST

需要回滚条件:DB_TRX_ID 在 UNCOMMIT_TRX_ID_LIST 或者 DB_TRX_ID >TRX_ID_NOW,回滚的操作:借助于 DB_ROLL_PTR 回滚指针所指向的取消日志,根据里面的信息构建出该条记录的历史版本,记历史版本的事务ID为 TRX_ID_HISTORY。DB_TRX_ID = TRX_ID_HISTORY 循环判断,直到不需要回滚为止。

读取不再需要回滚的历史版本的记录信息

msyql高性能优化中的 RR隔离级别下 MVCC是简洁版(建议看书)。具体实现如下图所示:

问题:

trx1 begin insert commit

trx2 begin selectselect commit

trx1 的系统版本号 小于 trx2的系统版本号

当trx1 执行insert操作的时候,不管使用trx1的系统版本号还是当前系统版本号即trx2 (按照书中的意思应该是trx2.Insert 使用的是当前系统版本号,结合前面的 每开始一个新的事务,系统版本号都会自动增加),该条插入记录的版本号 小于等于 事务系统版本号。且没有删除版本,所以在第二次select中就会被读出来。这样就会造成 不可一致性读的问题。

trx1的commit在前面就是因为 看到网上的分享说 这个mvcc只读已经提交的,所以用这个说明一下还是实现不了RR 。

比较而言,我是更倾向于 官方文档和唐成的这个解释。mysql高性能优化所说的是简版mvcc,而不是InnoDB mvcc的具体实现。

先把这个疑问记录下来,以后再慢慢看,慢慢思考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值