五、Read-View的构建与应用 Read-View的定义与构建过程 Read-View在一致性无锁读中的作用 Read-View与事务隔离级别的关系 Read-View的定义与构建过程 Read-View 生成Read-View:基于上述步骤,系统为当前事务生成一个Read-View,确保事务在其执行期间看到的是一致性的数据快照。 Read-View与事务隔离级别 Read-View的应用使得数据库能够支持不同的事务隔离级别。 每次查询都会生成一个新的Read-View。 REPEATABLE READ(可重复读): 事务在开始时创建一个Read-View,并在整个事务期间使用这个Read-View,确保可以多次读取到相同的数据快照。
快照 Read-View一致性读中的快照,在程序中医Read-View对象的形式存在。 所以事务ID比low_limit_id大的事务对记录所做的更新,都不应该被当前Read-View可见。 trx_ids: 创建当前Read-View时,还未提交的活跃事务的事务ID列表。creator_trx_id: 创建当前Read-View的事务ID。 基于MVCC、Read-View、Undo-log实现一致性无锁读有了前面的基础知识,我们来看下如何基于MVCC、Read-View、undo-log实现一致性无锁读。 在Read-View中我们维护了low_limit_id、up_limit_id、trx_ids, 将他们与MVCC、undo-log中的DB_TRX_ID列对比,即可得到哪些事务在创建Read-View
④read-view 当执行 SQL 语句查询时会产生一致性视图,也就是 read-view,它是由查询的那一时间所有未提交事务 ID 组成的数组,和已经创建的最大事务 ID 组成的。 对于此时生成的 read-view 你会有什么疑问,在 RR 级别也就是可重复读的隔离级别下。 当在一个事务下执行查询时,所有的 read-view 都是沿用的第一条查询语句生成的。 那此时的 read-view 也就是[100,101],102。 此时的 read-view 依然为[100,101],102。 那么来理一下寻找过程: 首先这里的 read-view 发生了变化,此时的 read-view 为[101],102。
创建SNMPv3组 [SWA]snmp-agent group v3 [group-name] {authentication | privacy} {read-view read-view | write-view read-view [read-view]:只读视图名,为1-32个字符的字符串。缺省值为ViewDefault。 bobview mib-2 [H3C]snmp-agent mib-view excluded bobview atTable [H3C]snmp-agent group v3 bobgroup privacy read-view
(其实我自己也感觉自己写的这个很难理解很不清楚,所以↓) 参考下面的(来自极客专栏): ~~(在可重复读的隔离级别下,如何理解**当系统里没有比这个回滚日志更早的 read-view 的时候**,这个回滚日志就会被删除 比如,在某个时刻(今天上午9:00)开启了一个事务A(对于可重复读隔离级别,此时一个视图read-view A也创建了),这是一个很长的事务…… 事务A在今天上午9:20的时候,查询了一个记录R1的一个字段 f1的值为1…… 今天上午9:25的时候,一个事务B(随之而来的read-view B)也被开启了,它更新了R1.f1的值为2(同时也创建了一个由2到1的回滚日志),这是一个短事务,事务随后就被commit 今天上午9:30的时候,一个事务C(随之而来的read-view C)也被开启了,它更新了R1.f1的值为3(同时也创建了一个由3到2的回滚日志),这是一个短事务,事务随后就被commit了。
我们在进行第三个事务的时候更新了一条数据在数据库底层会帮我们做这样一件事情 创建一条新数据然后将我们的旧数据放到回滚日志里边,并且将回滚指针指向它 此时我们进行一个查询会生成一个快照,他由指向查询时所有未提交事务id数组,和已创建事务id组成,查询数据需要跟read-view 下面进行一个新的查询 因为我们研究的是可重复读的情况所以会沿用上一次生成的快照 此时查询出来的数据还会是臧臧,那么这是为什么呢,分析一下 先说一些readview比对规则 当执行查询sql时会生成一致性视图read-view ,它由执行查询时所有未提交事务id数组(数组里最小的id为min_id)和已创建的最大事务id(max_id) 组成,查询的数据结构需要跟read-view做对比从而得到快照结果 版本链对比规则: 进行对比此时版本链是这样的 进行对比200在范围内,但是在未提交数组中所以不可见,以此类推,查出来的还是name=臧臧, 此时我们进行这样的操作新建一个会话,然后进行同样的查询操作,这个时候生成的read-view 是[200],300.因为我们此时生成快照的时间在100和300都提交的时刻所以read-view是这样的继续对比200在范围内,并且在未提交数组中不可见,上边一样,一直到100的时候,小于min_id
image.png 当前值是 4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的 read-view。 对于 read-view A,要得到 1,就必须将当前值依次执行图中所有的回滚操作得到. 同时你会发现,即使现在有另外一个事务正在将 4 改成 5,这个事务跟 read-view A、B、C 对应的事务是不会冲突的. 那什么时候删除回滚日志呢? 当系统里没有比这个回滚日志更早的 read-view 的时候 为什么建议你尽量不要使用长事务?
当前值是 4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的 read-view。 对于 read-view A,要得到 1,就必须将当前值依次执行图中所有的回滚操作得到。 每次开启事务的时候,都会有不同的 read-view ,同一条记录可以对应多种不同的版本。
假设一个值从 1 被按顺序改成了 2、3、4,在回滚日志里面就会有类似下面的记录 : 事务隔离的实现 当前值是 4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的 read-view。 对于 read-view A,要得到 1,就必须将当前值依次执行图中所有的回滚操作得到。 你会发现,即使现在有另外一个事务正在将 4 改成 5,这个事务跟 read-view A、B、C 对应的事务是不会冲突的。 那回滚日志总不能一直保留吧,什么时候删除呢? 系统会判断,当没有事务再需要用到这些回滚日志时,也就是当系统里没有比这个回滚日志更早的 read-view 的时候,回滚日志会被删除。 因此在使用数据库时,应尽量不要使用长事务。
通过事务ID可以查找到read-view上的记录RC隔离级别和RR隔离级别生成read-view的时机不一样,RR是在开始事务时,RC是在每一次查询,所以在RR隔离级别下,MVCC可以解决幻读问题。 read-view记录:m_ids:表示活跃事务id列表min_trx_id:活跃事务中的最小事务idmax_trx_id:已创建的最大事务idcreator_trx_id:当前的事务id版本链比对规则 若row的trx_id不在m_ids数组中,表示这个版本是已经提交了的事务生成的,可见 MySQL的InnoDB实现MVCC,就是在隔离级别为读已提交和可重复读,基于乐观锁理论,通过事务ID和read-view
当前值是4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的read-view。 对于read-view A,要得到1,就必须将当前值依次执行图中所有的回滚操作得到。 同时你会发现,即使现在有另外一个事务正在将4改成5,这个事务跟read-view A、B、C对应的 事务是不会冲突的。你一定会问,回滚日志总不能一直保留吧,什么时候删除呢? 就是当系统里没有比这个回滚日志更早的read-view的时候,换一种说法就是在这些事物提交之后。 3. 执行时间长,容易造成主从延迟 因为主库上必须等事务执行完成才会写入binlog,再传给备库。
snmp-agent sys-info version v3 //配置SNMP的协议版本 snmp-agent group v3 zabbix-group privacy read-view aes128 //回车,然后输入用户加密密码 华三设备 snmp-agent sys-info version all snmp-agent group v3 zabbix-group privacy read-view
当前值为4, 不同时刻启动的事务会看到不同的read-view。 8.MVCC 同一条记录可以在系统中有多个版本,这就是数据库的多版本并发控制。 9.什么时候会删除回滚日志 当没有事务用到回滚日志的时候,回滚日志会删除,也就是系统里没有比回滚日志更早的read-view的时候会删除日志。
DB_TRX_ID : 创建或最后修改记录的事务IDDB_ROW_ID : 隐藏主键DB_ROLL_PTR :Undo Log里的回滚指针,7byte大小read-view:事务在快照时产生的读视图。 up_limit_id,如果小于,则当前事务能看到DB_TRX_ID的记录,如果大于和等于,则进入下一个判断2.比较DB_TRX_ID和low_limit_id,如果大于等于则代表DB_TRX_ID的记录在read-view 3.判断DB_TRX_ID是否在活跃事务中,如果在,代表read-view生成时,事务还在活跃状态,修改的数据当前的事务是看不到的,如果不在,说明事务在read-view之前就commit了,那么修改的结果就是可见的
当前值4,但在查询这记录时,不同时刻启动事务有不同read-view。 在视图A、B、C,该记录的值分别是1、2、4,同一记录在系统中可存在多版本,即多版本并发控制(MVCC)。 对read-view A,要得到1,就必须将当前值依次执行图中所有的回滚操作得到。 即使现在有另外一个事务正在将4改成5,这个事务跟read-view A、B、C对应的事务是不会冲突的。 当系统里没有比该undo log更早的read-view时。 5 避免长事务 长事务意味着系统里面会存在很老的事务视图。
否则可能操作无效 SNMPV3可以自己定义所访问的MIB视图 SNMP组的用法 snmp-agent group { v1 | v2c } group-name [ read read-view ] [ v2c } group-name acl acl-number snmp-agent group v3 group-name [ authentication | privacy ] [ read read-view
4.1 示例 一个值从1被按顺改成2、3、4,undo log中的记录: 回滚段(rollback segment) 当前值4,但在查询该记录时,在不同时刻启动事务有不同read-view。 对read-view A,要得到1,就必须将当前值依次执行图中所有的回滚操作。 即使现在有另外一个事务正在将4改成5,这个事务跟read-view A、B、C对应的事务不会冲突。 何时不需要undo log 当系统里没有比该undo log更早的read-view时。 4.2 意义 保证事务的原子性。
小鱼先给各位同学讲解下版本链和一致性视图(read-view),先建立一个基本认识。 一致性视图(read-view) 在可重复读隔离级别下,当事务开启并执行查询语句时,MySQL 会生成当前事务的一致性视图,并且在事务结束之前,该视图不会变化。 在事务中任何查询结果都需要从相应的版本链中的最新数据开始逐条与read-view 进行对比,从而得到最终的快照结果。 在读已提交隔离级别下,每次查询都会生成新的一致性视图。
当前值是 4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的 read-view。 对于 read-view A,要得到 1,就必须将当前值依次执行图中所有的回滚操作得到。 同时你会发现,即使现在有另外一个事务正在将 4 改成 5,这个事务跟 read-view A、B、C 对应的事务是不会冲突的。 你一定会问,回滚日志总不能一直保留吧,什么时候删除呢? 就是当系统里没有比这个回滚日志更早的 read-view 的时候。 基于上面的说明,我们来讨论一下为什么建议你尽量不要使用长事务。 长事务意味着系统里面会存在很老的事务视图。
那么这个 read view 是由查询时所有未提交事务 ID 组成的数组,数组中最小的事务ID为 min_id 和已创建的最大事务 ID 为 max_id 组成,查询的数据结果需要跟 read-view 4. read-view 当执行SQL语句查询时会产生一致性视图,也就是read-view,它是由查询的那一时间所有未提交事务ID组成的数组,和已经创建的最大事务ID组成的。 在这个数组中最小的事务ID被称之为min_id,最大事务ID被称之为max_id,查询的数据结果要根据read-view做对比从而得到快照结果。 于是就产生了以下的对比规则,这个规则就是使用当前的记录的trx_id跟read-view进行对比,对比规则如下。 5. 如果你对这里的read-view的生成和版本链对比规则不懂,不要着急,也不要在这里浪费时间,请继续往下看,咔咔会使用一个简单的案例和一个复杂的案例给大家重现上述的规则。