一、 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. liunx搭建DHCP服务器以及DHCP中继服务器

    liunx搭建DHCP服务器以及DHCP中继服务器 一.实验拓扑 二.实验条件 虚拟机取消VMnet1和VMnet8的dhcp动态获取ip地址,以免影响实验 DHCPserver 网关以及DHCP中继 ...

  2. Linux: 软件包管理之rpm与yum [转]

    软件包的安装和卸载时很平常的事,但在Linux上面却不简单..Linux的其中一个哲学就是一个程序只做一件事,并且做好.组合小程序来完成复杂的任务,这样做有很多好处,但是各个小程序之间往往会存在着复杂 ...

  3. php学习----运算符

    PHP 1.运算符 加减乘除与数学运算无异 但PHP的赋值运算符有两种,分别是: (1)"=":把右边表达式的值赋给左边的运算数.它将右边表达式值复制一份,交给左边的运算数.换而言 ...

  4. 聚类——FCM的matlab程序

    聚类——FCM的matlab程序 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 在聚类——FCM文章中已介绍了FCM算法的理论知识,现在用matlab ...

  5. 在win10 64位系统安装 lxml (Python 3.5)

    本想直接用pip install lxml 命令安装完事,但是由于安装过程中跟VS的一些东西冲突怎么都安装不上,搜索到以下方法,问题解决. 步骤: 1.下载跟python匹配的.whl 文件(lxml ...

  6. bootstrap的datepicker在选择日期后调用某个方法

    bootstrap的datepicker在选择日期后调用某个方法 2016-11-08 15:14 1311人阅读 评论(0) 收藏 举报 首先感谢网易LOFTER博主Ivy的博客,我才顿悟了问题所在 ...

  7. 获取当前页面的URL信息

    以前在做网站的时候,经常会遇到当前页的分类高亮显示,以便让用户了解当前处于哪个页面.之前一直是在每个不同页面写方法.工程量大,也不便于修改.一直在想有什么简便的方法实现.后来在网上查到可以用获取当前U ...

  8. 解决不能再jupyter notebook中使用tensorflow

    在搭建cuda + Anaconda + tensorflow的开发环境时,在虚拟环境中的jupyter notebook启动后无法导入tensorflow.具体解决方案如下: 1.首先在虚拟环境中安 ...

  9. ORA-27154: post/wait create failed ORA-27300 ORA-27301 ORA-27302

    今天刚装了Oracle 11g,配制好了之后启动数据库时遇到下面的错误:SQL> startupORA-27154: post/wait create failedORA-27300: OS s ...

  10. Redo丢失的4种情况及处理方法

    这篇文章重点讨论Redo丢失的几种情况,及每种情况的处理方法. 一.说明:1.以下所说的当前日志指日志状态为CURRENT,ACTIVE,非当前日志指日志状态为INACTIVE2.不用考虑归档和非归档 ...