InnoDB MVCC何时创建read view

Stella981
• 阅读 751

导读

InnoDB MVCC是事务一启动就创建read view,还是什么时候?

几个关于事务的基本概念

说到事务,我们不得不先说下什么是ACID、MVCC、consistent read、read view 等几个基本概念。

ACID

ACID是事务的原子性、一致性、隔离性、持久性4个单词的首字母缩写。所有的事务型数据库系统都遵循这4个特性,InnoDB亦是如此。关于ACID的具体解释请自行 google/bing。

MVCC

是multiversion concurrency control的简称,也就是多版本并发控制,是个很基本的概念。MVCC的作用是让事务在并行发生时,在一定隔离级别前提下,可以保证在某个事务中能实现一致性读,也就是该事务启动时根据某个条件读取到的数据,直到事务结束时,再次执行相同条件,还是读到同一份数据,不会发生变化(不会看到被其他并行事务修改的数据)

有了 MVCC 就可以提高事务的并行度,因为可以利用锁机制实现资源控制而无需等待其他事务先执行。

read view

InnoDB MVCC使用的内部快照的意思。在不同的隔离级别下,事务启动时(有些情况下,可能是SQL语句开始时)看到的数据快照版本可能也不同。在RR、RC、RU(READ UNCOMMITTED)等几个隔离级别下会用到 read view。

一致性读

读请求基于某个时间点得到一份那时的数据快照,而不管同时其他事务对数据的修改。查询过程中,若其他事务修改了数据,那么就需要从 undo log中获取旧版本的数据。这么做可以有效避免因为需要加锁(来阻止其他事务同时对这些数据的修改)而导致事务并行度下降的问题。

在可重复读(REPEATABLE READ,简称RR)隔离级别下,数据快照版本是在第一个读请求发起时创建的。在读已提交(READ COMMITTED,简称RC)隔离级别下,则是在每次读请求时都会重新创建一份快照。

一致性读是InnoDB在RR和RC下处理SELECT请求的默认模式。由于一致性读不会在它请求的表上加锁,其他事务可以同时修改数据不受影响。

何时创建read view

其实,我们从上面的解释已经明白了,在RC隔离级别下,是每个SELECT都会获取最新的read view;而在RR隔离级别下,则是当事务中的第一个SELECT请求才创建read view。

我们通过几个例子来加强下。

1. RR级别

首先,确认隔离级别

yejr@imysql.com [test]>select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+

测试1:事务启动后立即发起SELECT请求

session1

session2

begin;

begin;

select * from t1 where a=10;
+----+------+---+ 
| a | b | c |
+----+------+---+
| 10 | 8 | 1 |

select * from t1 where a=10;
+----+------+---+
| 10 | 8 | 1 |

事务中第一个SELECT立即创建read view

update t1 set c=10 where a=10;

Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

select * from t1 where a=10;
+----+------+---+
| 10 | 8 | 1 |

再次读取,结果还是一样

commit;

提交事务

select * from t1 where a=10;
+----+------+---+
| 10 | 8 | 1 |

再次读取,结果仍然一样

结论可见:RR中第一个SELECT已经创建好read view,之后不会再发生变化

测试2:另一个事物提交后才发起SELECT请求

session1

session2

begin;

begin;

select * from t1 where a=10;
+----+------+---+ 
| a | b | c |
+----+------+---+
| 10 | 8 | 1 |

update t1 set c=10 where a=10;

Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

commit;

提交事务

select * from t1 where a=10;
+----+------+---+
| 10 | 8 | 10 |

session1提交后才发起SELECT,可以读取到最新版本

结论可见:RR中是发起SELECT时才创建read view,而不是事务刚启动时就创建

2. RC级别

根据上面提到的说法,RC隔离级别下,是每次发起SELECT都会创建read view,也就是每次SELECT都能读取到已经COMMIT的数据,所以才存在不可重复读、幻读 现象。

修改&确认隔离级别

yejr@imysql.com [test]>set session transaction isolation level read committed;

yejr@imysql.com [test]>select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+

开始测试

session1

session2

begin;

begin;

select * from t1 where a=10;
+----+------+---+ 
| a | b | c |
+----+------+---+
| 10 | 8 | 101 |

select * from t1 where a=10;
+----+------+---+ 
| a | b | c |
+----+------+---+
| 10 | 8 | 101 |

update t1 set c=102 where a=10;commit;

Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

Query OK, 0 rows affected (0.02 sec)

select * from t1 where a=10;
+----+------+---+
| 10 | 8 | 102 |

session1提交后再次发起SELECT,可以读取到最新版本

begin;update t1 set c=103 where a=10;commit;

Query OK, 0 rows affected (0.00 sec)

Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

Query OK, 0 rows affected (0.02 sec)

select * from t1 where a=10;
+----+------+---+
| 10 | 8 | 103 |

再次发起SELECT,又可以读取到最新版本

总结

  • RR级别下,事务中的第一个SELECT请求才开始创建read view;

  • RC级别下,事务中每次SELECT请求都会重新创建read view;

延伸阅读

知识无界限,不再加原创

喜欢就转走,铁粉加密圈

InnoDB MVCC何时创建read view

好铁观音尽在

「老叶茶馆」

http://yejinrong.com

InnoDB MVCC何时创建read view

本文分享自微信公众号 - 老叶茶馆(iMySQL_WX)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
MySQL数据库InnoDB存储引擎Log漫游(1)
作者:宋利兵来源:MySQL代码研究(mysqlcode)0、导读本文介绍了InnoDB引擎如何利用UndoLog和RedoLog来保证事务的原子性、持久性原理,以及InnoDB引擎实现UndoLog和RedoLog的基本思路。00–UndoLogUndoLog是为了实现事务的原子性,
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这