MySQL MVCC原理
https://www.cnblogs.com/chinesern/p/7592537.html
1 MVCC基本原理
MVCC:多版本并发控制(MVCC,Multiversion Currency Control)。一般情况下,事务性储存引擎不是只使用表锁,行加锁的处理数据,而是结合了MVCC机制,以处理更多的并发问题。Mvcc处理高并发能力最强,
但系统开销 比最大(较表锁、行级锁),这是最求高并发付出的代价。
** InnoDB实现MVCC的方法是,它存储了每一行的三个额外的隐藏字段:**
1.DB_TRX_ID:一个6byte的标识,每处理一个事务,其值自动+1
#下面提到的“创建时间”和“删除时间”记录的就是这个DB_TRX_ID的值
#如insert、update、delete操作时,删除操作用1个bit表示。
#DB_TRX_ID是最重要的一个,可以通过语句“show engine innodb status”来查找
2.DB_ROLL_PTR: 大小是7byte,指向写到rollback segment(回滚段)的一条undo log记录
(update操作的话,记录update前的ROW值)
3.DB_ROW_ID: 大小是6byte,该值随新行插入单调增加。
#当由innodb自动产生聚集索引时聚集索引(即没有主键时,因为MYSQL默认聚簇表,会自动生成一个ROWID)
#包括这个DB_ROW_ID的值,
#不然的话聚集索引中不包括这个值,这个用于索引当中。
DB_TRX_ID记录了行的创建的时间删除的时间在每个事件发生的时候,每行存储版本号,而不是存储事件实际发生的时间。每次事物的开始这个版本号都会增加。自记录时间开始,每个事物都会保存记录的系统版本号。
依照事物的版本来检查每行的版本号。在insert操作时 “创建时间”=DB_TRX_ID,这时,“删除时间”是未定义的;在update时,复制新增行的“创建时间”=DB_TRX_ID,删除时间未定义,旧数据行“创建时间”不变,
删除时间=该事务DB_TRX_ID;delete操作,相应数据行的“创建时间”不变,删除时间=该事务的DB_ROW_ID;select操作对两者都不修改,只读相应的数据
MVCC结合隔离级别:
1.READ UNCOMMITTED ,不适用MVCC读,可以读到其他事务修改甚至未提交的
2.READ COMMITTED ,其他事务对数据库的修改,只要已经提交,其修改的结果就是可见的,
与这两个事务开始的先后顺序无关,不完全适用于MVCC读,
3.REPEATABLE READ,可重复读,完全适用MVCC,只能读取在它开始之前已经提交的事务对数据库的修改,
在它开始以后,所有其他事务对数据库的修改对它来说均不可见
4.SERIALIZABLE ,完全不适合适用MVCC,这样所有的query都会加锁,再它之后的事务都要等待
MVCC只工作在REPEATABLE READ和READ COMMITED隔离级别下
2 REPEATABLE READ 可重复读下的MVCC
##### SELECT
Innodb检查没行数据,确保他们符合两个标准:
1.InnoDB只查找版本早于当前事务版本的数据行(也就是数据行的版本必须小于等于事务的版本),这确保当前事务
读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行
2.行的删除操作的版本一定是未定义的或者大于当前事务的版本号。确定了当前事务开始之前,行没有被删除
符合了以上两点则返回查询结果。
INSERT
InnoDB为每个新增行记录当前系统版本号作为创建ID。
DELETE
InnoDB为每个删除行的记录当前系统版本号作为行的删除ID。
UPDATE
InnoDB复制了一行。这个新行的版本号使用了系统版本号。它也把系统版本号作为了删除行的版本。
3 MVCC深入
如果根据事务DB_TRX_ID去比较获取事务的话,按道理在一个事务B(在事务A后,但A还没commit)select的话 B.DB_TRX_ID>A.DB_TRX_ID则应该能返回A事务对数据的操作以及修改。那不是和前面矛盾?其实不然。
InnoDB每个事务在开始的时候,会将当前系统中的活跃事务列表(trx_sys->trx_list)创建一个副本(read view),然后一致性读去比较记录的tx id的时候,并不是根据当前事务的tx id,而是根据read view最早一个事务的tx id(read view->up_limit_id)来做比较的,这样就能确保在事务B之前没有提交的所有事务的变更,B事务都是看不到的。当然,这里还有个小问题要处理一下,就是当前事务自身的变更还是需要看到的。
原文地址:https://www.cnblogs.com/fengff/p/11763503.html
- SpringBoot工作机制
- Android权限管理PermissionsDispatcher2.3.2使用+原生6.0权限使用
- SpringBoot中的IoC
- Sonar安装配置
- 《AngularJS深度剖析与最佳实践》推荐序
- JavaScript递归方法 生成 json tree 树形结构数据
- springboot使用hibernate validator校验
- 机器学习(三) ——k-近邻算法基础
- SpringBoot实战 之 异常处理篇
- ES6的Promise
- vue input输入框联想
- Sonar本地环境搭建
- Spark强大的函数扩展功能
- SpringBoot-Mybatis_Plus学习记录之公共字段自动填充
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- chkconfig学习笔记
- 3分钟短文:说说Laravel通用缓存Cache的使用技巧
- 【技术创作101训练营】想用代码改变世界?先用好Git和Github!
- 绘制散点图(克利夫兰系列)
- 绘制分组散点图(克里夫兰点图)
- ggplot2绘制玫瑰图
- 绘制极坐标系条形图
- 四步重新认识冗余机器人的控制器设计
- 人脸识别接入常见问题汇总
- TKE上关于postStart 和preStop使用
- 文字识别接入常见问题
- 从 1 到 0 构建博客项目(2) -- 操作系统篇(2)--定制Centos
- 使用Angular依赖注入自定义SAP Spartacus的ProductAdapter
- 获取SAP Spartacus当前显示产品json数据的又一办法
- SAP Spartacus注入自定义的CurrentProductService