Mysql 中的MVCC原理,undo日志的依赖
原文点击: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 的影响:
innodb 只会去查找版本好小于或等于(早于)当前事务ID的数据行,这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的
行的删除版本要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除.
只有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日志的依赖的更多相关文章
- MySQL中redo log、undo log、binlog关系以及区别
MySQL中redo log.undo log.binlog关系以及区别 本文转载自:MySQL中的重做日志(redo log),回滚日志(undo log),以及二进制日志(binlog)的简单总结 ...
- Mysql中主从复制的原理、配置过程以及实际案例
Mysql中主从复制的原理.配置过程以及实际案例1.什么是主从复制?原理:主从分离,什么意思呢?我们不妨画个图看看.如图1所示: 2.准备工作:预备两台服务器,我这里使用虚拟机安装了两个Centos6 ...
- MySQL中几种常见的日志
前言: 在 MySQL 系统中,有着诸多不同类型的日志.各种日志都有着自己的用途,通过分析日志,我们可以优化数据库性能,排除故障,甚至能够还原数据.这些不同类型的日志有助于我们更清晰的了解数据库,在日 ...
- MySQL中的事务原理和锁机制
本文主要总结 MySQL 事务几种隔离级别的实现和其中锁的使用情况. 在开始前先简单回顾事务几种隔离级别以及带来的问题. 四种隔离级别:读未提交.读已提交.可重复读.可串行化. 带来的问题:脏读.不可 ...
- 面试官:什么是MySQL 事务与 MVCC 原理?
作者:小林coding 图解计算机基础网站:https://xiaolincoding.com/ 大家好,我是小林. 之前写过一篇 MySQL 的 MVCC 的工作原理,最近有读者在网站上学习的时候, ...
- 说说MySQL中的Redo log Undo log都在干啥
在数据库系统中,既有存放数据的文件,也有存放日志的文件.日志在内存中也是有缓存Log buffer,也有磁盘文件log file,本文主要描述存放日志的文件. MySQL中的日志文件, ...
- MySql中innodb存储引擎事务日志详解
分析下MySql中innodb存储引擎是如何通过日志来实现事务的? Mysql会最大程度的使用缓存机制来提高数据库的访问效率,但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据 ...
- 【转】说说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 空间管理 ...
- mysql中slow query log慢日志查询分析
在mysql中slow query log是一个非常重要的功能,我们可以开启mysql的slow query log功能,这样就可以分析每条sql执行的状态与性能从而进行优化了. 一.慢查询日志 配置 ...
随机推荐
- monkey_recorder录制monkeyrunner脚本
转载:monkey_recorder录制monkeyrunner脚本 1. 你必须有android sdk, sdk的tools文件家里有一个monkeyrunner.bat.2. 将如下内容拷贝 ...
- centos下安装memcached
1. 通过yum安装 yum -y install memcached #安装完成后执行: memcached –h 2. Memcached 运行 //查看考号修改配置 vim /etc/s ...
- ps流提取H264并解码播放
因为需要从海康ps流中提取H264数据并进行解码播放,才有了这篇文章.因为是视频编解码领域的纯入门新手,个别理解或者方法有误,需要自行判断,不过相关方法已经测试通过,对于 像我这样的新手还是有一定的借 ...
- LeetCode算法题-Invert Binary Tree
这是悦乐书的第194次更新,第199篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第55题(顺位题号是226).反转二叉树.例如: 输入: 4 / \ 2 7 / \ / ...
- February 23rd, 2018 Week 8th Friday
It takes a strong man to save himself, and a great man to save another. 强者自救,圣者渡人. When you are not ...
- 微服务---Eureka注册中心(服务治理)
在上一篇的初识SpringCloud微服务中,我们简单讲解到服务的提供者与消费者,当服务多了之后,会存在依赖与管理之间混乱的问题,以及需要对外暴露自己的地址,为了解决此等问题,我们学习Eureka注册 ...
- VMware中某个虚拟机卡死,单独关闭某个虚拟机的办法
在虚拟机中部署ceph时,其中一个虚拟机突然意外卡死,网络搜索到解决的办法,特此整理如下: 一.找到卡死虚拟机的安装目录,在安装目录下找到VMware这个文本文档 二.打开该文本文档,在文档中查找pi ...
- dubbo远程方法调用的基本原理
1 dubbo是远程服务调用rpc框架 2 dubbo缺省协议采用单一长连接和NIO通讯 1client端生成一个唯一的id,封装方法调用信息obj(接口名,方法名,参数,处理结果的回调对象),在全局 ...
- [matlab] 4.M函数
函数文件的编写 新建一个函数文件 函数的第一行的格式 :function [输出的参数] =函数名 (输入的参数) 输入和输出的参数可以有多个 保存函数文件的时候,注意文件名要和函数名一样 函数头和函 ...
- Python:Day44 Javascript
一个完整的Javascript实现是由三个不同的部分组成: 1.核心 ECMA Javascript 2.浏览器对象模型(DOM) document object model (整合JS.html.C ...