一、 MVCC 原理了解

原文点击:MVCC原理浅析

  • 读锁:

    也叫共享锁、S锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

  • 写锁:

    又称排他锁、X锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。

  • 表锁:

    操作对象是数据表。Mysql大多数锁策略都支持(常见mysql innodb),是系统开销最低但并发性最低的一个锁策略。事务t对整个表加读锁,则其他事务可读不可写,若加写锁,则其他事务增删改都不行。

  • 行级锁:

    操作对象是数据表中的一行。是MVCC技术用的比较多的,但在MYISAM用不了,行级锁用mysql的储存引擎实现而不是mysql服务器。但行级锁对系统开销较大,处理高并发较好。

  • Autocommit:

    mysql一个系统变量,默认情况下autocommit=1表示mysql把没一条sql语句自动的提交,而不用commit语句。所以,当要开启事务操作时,要把autocommit设为0,可以通过“set session autocommit=0; ”来设置

  • MVCC: (MVCC,Multiversion Currency Control)

    多版本并发控制。一般情况下,事务性储存引擎不是只使用表锁,行加锁的处理数据,而是结合了MVCC机制,以处理更多的并发问题。Mvcc处理高并发能力最强,但系统开销比最大(较表锁、行级锁),这是最求高并发付出的代价。

     

    当使用锁(尤其排他锁-行锁)进行并发控制,开销是非常大的 ,而使用MVCC机制来做,能一定程度的代替行锁,就可以有效降低系统开销

InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,分别保存了这个行的创建时间,一个保存的是行的删除时间。这里存储的并不是实际的时间值,而是系统版本号(可以理解为事务的ID),没开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID.

话外内容:############开始###############

InnoDB的内核,会对所有row数据增加三个内部属性:

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的值,

不然的话聚集索引中不包括这个值,这个用于索引当中。

话外内容:############结束###############

如:列子,假设版本好初始为1

create table tb(

id int auto_increment primary key,

name cahr(32));

创建几条数据:insert 操作:第一个事务ID为1

start transaction;
insert into tb(name) values('shenjian') ;
insert into tb(name) values('zhangshan');
insert into tb(name) values('lisi');
commit;
id name 创建时间(事务ID) 删除时间(事务ID)
1 shenjian 1 undefinded
2 zhangsan 1 undefinded
3 lisi 1 undefinded

对select 的影响:

  1. innodb 只会去查找版本好小于或等于(早于)当前事务ID的数据行,这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的

  2. 行的删除版本要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除.

    只有1、2同时满足的记录,才能返回作为查询结果.

例2:delete操作

InnoDB会为删除的每一行保存当前系统的版本号(事务的ID)作为删除标识.

看下面的具体例子分析:

第二个事务,ID为2;

start transaction;
select * from tb; //(第一步操作:1)
select * from tb; //(第二部操作:2)
commit;

假设:在这个事务的的执行过程中到第一步操作:1 的时候。

又开启了一个新事务(ID 为3)向表中执行Insert 操作插入数据

start transaction;
insert into tb(name) values('wangwu') ;
commit;

此时的表中数据为:

id name 创建时间(事务ID) 删除时间(事务ID)
1 shenjian 1 undefinded
2 zhangsan 1 undefinded
3 lisi 1 undefinded
4 wangwu 3 undefinded

然后刚才事务2,中的第二步:2 开始执行,引文id=4的数据的创建时间(事务ID为3),执行当前事务的ID为2,而InnoDB只会查找事务ID小于等于当前事务ID的数据行,所以id=4的数据行并不会在执行事务2中的第二步:2 中被检索出来,在事务2中的两条select 语句检索出来的数据都只会下表:

id name 创建时间(事务ID) 删除时间(事务ID)
1 shenjian 1 undefinded
2 zhangsan 1 undefinded
3 lisi 1 undefinded

再假设:假设在执行事务ID为2的过程中,刚执行到了第一步:1,假设事务执行完事务3后,接着又执行了事务4;

事务4:

st art transaction;
delete from tb where id=1;
commit;

此时数据库中的表为:

id name 创建时间(事务ID) 删除时间(事务ID)
1 shenjian 1 4
2 zhangsan 1 undefinded
3 lisi 1 undefinded
4 wangwu 3 undefinded

接着执行事务ID为2的第二步:2,根据select 检索条件可以知道,它会检索创建时间(创建事务的ID)小于当前事务ID的行和删除时间(删除事务的ID)大于当前事务的行,而id=4的行上面已经说过,而id=1的行由于删除时间(删除事务的ID)大于当前事务的ID,所以事务2的第二步:2 select * from tb 会把id=1的数据检索出来.所以,事务2中的两条select 语句检索出来的数据都如下:

id name 创建时间(事务ID) 删除时间(事务ID)
1 shenjian 1 4
2 zhangsan 1 undefinded
3 lisi 1 undefinded

update:

InnoDB执行UPDATE,实际上是新插入了一行记录,并保存其创建时间为当前事务的ID,同时保存当前事务ID到要UPDATE的行的删除时间.

再再假设:

假设在执行完事务2的第一步:1 后又执行,其它用户执行了事务3,4,这时,又有一个用户对这张表执行了UPDATE操作:

第5个事务:

start transaction;
update tb set name='xxx' where id=2;
commit;

按照update的更新原则:会生成新的一行,并在原来要修改的列的删除时间列上添加本事务ID,得到表如下:

id name 创建时间(事务ID) 删除时间(事务ID)
1 shenjian 1 4
2 zhangsan 1 5
3 lisi 1 undefinded
4 wangwu 3 undefinded
2 xxx 5 undefinded

继续执行事务2第二步:2,根据select 语句的检索条件(创建时间事务ID小于自己查询事务ID的,和删除时间事务ID大于自身的查询事务ID),得到下表:

id name 创建时间(事务ID) 删除时间(事务ID)
1 shenjian 1 4
2 zhangsan 1 5
3 lisi 1 undefinded

并得不到上上个表的ID=4的第四行(因为创建事务ID=3 > 查询事务ID=2) 和第五行Update 事务创建的ID=2 的更新数据(因为 创建他的Update 事务ID=5 > 查询事务ID=2)

Mysql 中的MVCC原理,undo日志的依赖的更多相关文章

  1. MySQL中redo log、undo log、binlog关系以及区别

    MySQL中redo log.undo log.binlog关系以及区别 本文转载自:MySQL中的重做日志(redo log),回滚日志(undo log),以及二进制日志(binlog)的简单总结 ...

  2. Mysql中主从复制的原理、配置过程以及实际案例

    Mysql中主从复制的原理.配置过程以及实际案例1.什么是主从复制?原理:主从分离,什么意思呢?我们不妨画个图看看.如图1所示: 2.准备工作:预备两台服务器,我这里使用虚拟机安装了两个Centos6 ...

  3. MySQL中几种常见的日志

    前言: 在 MySQL 系统中,有着诸多不同类型的日志.各种日志都有着自己的用途,通过分析日志,我们可以优化数据库性能,排除故障,甚至能够还原数据.这些不同类型的日志有助于我们更清晰的了解数据库,在日 ...

  4. MySQL中的事务原理和锁机制

    本文主要总结 MySQL 事务几种隔离级别的实现和其中锁的使用情况. 在开始前先简单回顾事务几种隔离级别以及带来的问题. 四种隔离级别:读未提交.读已提交.可重复读.可串行化. 带来的问题:脏读.不可 ...

  5. 面试官:什么是MySQL 事务与 MVCC 原理?

    作者:小林coding 图解计算机基础网站:https://xiaolincoding.com/ 大家好,我是小林. 之前写过一篇 MySQL 的 MVCC 的工作原理,最近有读者在网站上学习的时候, ...

  6. 说说MySQL中的Redo log Undo log都在干啥

        在数据库系统中,既有存放数据的文件,也有存放日志的文件.日志在内存中也是有缓存Log buffer,也有磁盘文件log file,本文主要描述存放日志的文件.     MySQL中的日志文件, ...

  7. MySql中innodb存储引擎事务日志详解

    分析下MySql中innodb存储引擎是如何通过日志来实现事务的? Mysql会最大程度的使用缓存机制来提高数据库的访问效率,但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据 ...

  8. 【转】说说MySQL中的Redo log Undo log都在干啥

    阅读目录(Content) 1 undo 1.1 undo是啥 1.2 undo参数 1.3 undo空间管理 2 redo 2.1 redo是啥 2.2 redo 参数 2.3 redo 空间管理 ...

  9. mysql中slow query log慢日志查询分析

    在mysql中slow query log是一个非常重要的功能,我们可以开启mysql的slow query log功能,这样就可以分析每条sql执行的状态与性能从而进行优化了. 一.慢查询日志 配置 ...

随机推荐

  1. Cs231n课堂内容记录-Lecture1 导论

    Lecture 1 视频网址:https://www.bilibili.com/video/av17204303/?p=2 https://zhuanlan.zhihu.com/p/21930884? ...

  2. Git&GitHub

    Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理.  Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软 ...

  3. 删除window10没用的服务

    最近学习了下resin,出了个问题,它默认端口是8080,跟Tomcat冲突了,我在使用的时候遇到了个奇怪的事情,resin4.0一直占用着我的8080端口,哪怕我用dos命令把它强制停止,不出五秒钟 ...

  4. CSS 浮动(float)与定位(position)

    一.浮动 1.三个属性:left.right.none. 2.特点:容易造成父项塌陷,故在父项需要清除浮动 3.父项塌陷现象 4.父项塌陷解决方案(建议使用):清除浮动 .parent:after{ ...

  5. 部署tinyproxy代理服务

    #安装依赖 yum install asciidoc #下载 wget https://github.com/tinyproxy/tinyproxy/releases/download/1.8.4/t ...

  6. Nginx使用教程(四):提高Nginx网络吞吐量之buffers优化

    请求缓冲区在NGINX请求处理中起着重要作用. 在接收到请求时,NGINX将其写入这些缓冲区. 这些缓冲区中的数据可作为NGINX变量使用,例如$request_body. 如果缓冲区与请求大小相比较 ...

  7. (转)Spring Boot(十七):使用 Spring Boot 上传文件

    http://www.ityouknow.com/springboot/2018/01/12/spring-boot-upload-file.html 上传文件是互联网中常常应用的场景之一,最典型的情 ...

  8. Shiro+JWT+Spring Boot Restful简易教程

    序言 我也是半路出家的人,如果大家有什么好的意见或批评,请务必issue下. 项目地址:https://github.com/Smith-Cruise/Spring-Boot-Shiro . 如果想要 ...

  9. go第三方日志系统-seelog-使用文档

    参考:https://godoc.org/github.com/cihub/seelog 导入方式: import "github.com/cihub/seelog" 包seelo ...

  10. zookeeper的原理,5分钟了解zookeeper

    一 .Zookeeper功能简介 ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现.分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/ ...