MySQL四种隔离级别和MVCC
事务在一个数据库中的地位尤为重要,尤其是高并发的场合。保证数据库操作的原子性和错误出现情况下的回滚,对数据的安全性和可靠性提供了保障。事务有四大原则,即ACID原则。网上关于这个问题的文章有很多,读者可以到网上看看相关的文章,我这里就不赘述了。但是需要注意的是,MySQL默认是不开启事务的,默认情况是autocommit自动提交,而如果想开启事务,需要数据库管理员或者开发者手动输入begin来开启事务。
本文主要介绍四大原则中的I原则,即隔离级别。并在讲述I原则的时候,顺带讨论MVCC。因为MVCC通常和隔离级别是讨论到一块的。
事务的隔离级别其实是SQL语言的标准,这里我就以自己比较常用的MySQL数据库为例进行介绍。
客户端输入命令:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
小提示:也可以使用小写,MySQL是不分大小写的。
在MySQL Workbench输入命令查询系统默认的隔离状态
MySQL默认情况下是repeatable read。
设置当前会话隔离级别
设置当前会话(客户端)的隔离级别,当客户端关闭后重新进入,隔离级别会恢复到系统的全局隔离状态。
理解‘当前会话’:
MySQL中认为,打开一个客户端就是开启一个会话。其实质是建立一个网络连接。这个网络连接是有状态性的,一旦关闭,此会话级别中设置的变量就会恢复为系统的变量。
设置全局隔离级别
设置全局隔离级别的时候,只对全局进行修改,当前会话还是会保持原来的设置,退出重新登录才会遵循全局的设置。
在MySQL Workbench中输入命令:
或者在终端输入
mysql> show variables like '%isolation';
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
| tx_isolation | READ-COMMITTED |
+---------------- ------+----------------+
2 rows in set, 1 warning (0.00 sec)
另外一种方法:
在ini文件(Linux为conf文件)设置全局的隔离级别
[mysqld]
添加:
transaction-isolation = READ-COMMITTED
不过这种情况需要重启服务器,所以不太建议使用这种方式,除非是几乎没有请求的深夜时候进行。
C:\WINDOWS\system32> net stop mysql MySQL 服务正在停止.. MySQL 服务已成功停止。 C:\WINDOWS\system32> net start mysql MySQL 服务正在启动 . MySQL 服务已经启动成功。
关于以上命令,有一些需要理解的点:
1)隔离级别优先级顺序 read uncommittd < read committed < repeatable read < serializable
我的理解是每一个级别都是在上一级别的基础上增加了表操作的限制。读者往下看就可以体会到这种限制的加强。
2)session和global
1. 默认行为(不带session和global)是为下一个(未连接)会话设置隔离级别。
2. 如果使用GLOBAL关键字,此命令语句在全局中对从那点开始创建的所有新连接设置事务级别。
3. 使用SESSION 关键字为当前连接上执行的事务设置默认事务级别。
4. 任何客户端在任何时候都能自由改变会话/全局隔离级别(甚至在事务的中间),或者为下一个事务设置隔离级别。
实际测试中,由于是本地连接,一些情况无法模拟出来,而且手动也很难做一些模拟高并发的情形,可以借助一些测试工具来进行。例如sysbench,《高性能MySQL》中也有一章专门写了基准测试。
下面是对四个隔离级别的介绍
1. Read Uncommitted 读取未提交的事务
一个数据库连接实例中,它的未提交事务执行了对数据库的增删改操作,这些操作对数据的更改是没有提交到服务器磁盘的,但是在高并发的情况下,本连接的事务会不断更新数据库以获取其他连接的事务对数据库进行的最新的更改。那么第一个事务查询操作读取的数据可能是不真实的,人家都还没有提交!所以这种情况下就会出现了所谓的脏读。一般,在现实中很少使用这个级别,除非是对数据的真实性要求不高,只想获得最新的数据的情况。想想在一些金融领域的电子现金系统或者商城购物车系统使用这个级别会是怎样一个情形?
2. Read Committed 读取已经提交的事务
此级别在本会话中对数据库进行查询,会读取已经提交(commit)了SQL语句的事务结果,而未提交的事务的操作对数据库所造成的影响是不会读取的。可以这样理解,这个级别更像是‘事务级别’,即不同事务间内部的操作互不影响,只有提交了事务才会对其他事务产生影响。
Read committed级别同时也是nonrepeatable read级别(是相对下面的Repeatable Read而言的),即不要求重复读。一个事务前后两次的读取内容可以是不同的,即允许在本事务查询的过程中其他事务对本事务查询的数据进行其他操作,这样就会出现前后两次读取的数据的不一致性。此处涉及到MVCC和乐观锁、悲观锁的概念,后面会讲述。我们先讨论这种机制的运行逻辑。
想象一下下面这种情形:高并发情况下,多个数据库连接同时对数据库提交操作。本事务由于SQL语句比较多,执行起来比较慢。而在这期间(有时可能是1s内),有另外两个连接同时在执行操作,一个连接对一行数据的某一列进行增加2操作,而另外一个连接对同一行数据的这一列数据进行减3操作,它们在对数据库的实现上可能相差的时间很小,可能仅在毫秒之间这个时候就会出现两个vesion版本的结果,一个是执行了一个事务的版本,另一个是执行了两个事务的版本。那么本事务究竟读取哪一个版本呢?答案是指读取执行了两条事务的版本。因为在本事务内,会不断去‘查看’其他事务的提交情况,并将最新的提交情况‘反馈’在本事务中。
3. Repeatable Read 可重复读
Repeatable Read正好与上面的Read Committed相反,本事务会读取第一个version的数据。因为在进行第一次查询操作的时候,可能第一个事务已经提交了,而第二个事务还没提交。而无论后面第二个事务甚至更多个事务提交了,但本事务中再次读取的数据时只会读取是第一读取的相同数据,即‘无视’其他事务对此行数据的更改。可以理解,在这里是悲观锁发挥了作用,即锁住了本事务,其他事务的数据的更改就无法影响到本事务。而在Read Committed级别中,发挥作用的是乐观锁,其实就是什么也不锁定,只在更新数据的时候锁定(下面有更详细描述)。所以在本事务的前后两次范围查询中会出现数据不一致的幻读现象。
4. Serilizable 串行化
数据库最高级别的隔离限制,事务与事务之间串行化的。即一个事务在执行任何操作的时候,都不允许其他事务对本事务查询范围内的数据有任何操作,这里会引入一个共享锁的概念,即本事务的查询操作别读取的数据锁住了,必须等本事务完成之后才允许其他事务获取这个共享锁进行其他操作,就好比如排着队一个个执行。
MVCC
MVCC, Multiversion Concurrency Control多版本并发控制。MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作, 因此服务器的开销更低(减少了锁的生产和分配)。虽然实现机制有所不同, 但大都实现了非阻塞的读操作,写操作也只锁定必要的行。
在实现上,MySQL通过三个列实现对版本的控制,即6字节的事务ID(DB_TRX_ID)字段,7字节的回滚指针(DB_ROLL_PTR)字段 ,6字节的DB_ROW_ID字段。更多相关内容推荐看这篇文章,里面讲得很详细 https://juejin.im/entry/5a4b52eef265da431120954b
而实际上InnoDB并非完全意义上的MVCC,因为没有实现多版本并存。关键在于并存两字,即在事务执行对数据操作时同时存在多个版本。而无论如何MySQL在事务执行的时候是串行化的,即使这两个事务几乎同时发生。其实这正是对数据安全性的一个保障。
MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作。其他两个隔离级别和MVCC不兼容。
悲观锁:
悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。
乐观锁:
乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完事务操作需要实际更新数据的最后一步再去拿一下锁就好。
在实战中怎么使用,还是要看具体的数据量和业务逻辑来进行选择。
更新说明:随着自己对MySQL数据库隔离级别的更多理解,本文在之前的内容基础上进行重新整理,并且添加上了MVCC的内容。18.12.25
参考文章:
https://www.cnblogs.com/phpper/p/7345332.html
https://juejin.im/entry/5a4b52eef265da431120954b
MySQL四种隔离级别和MVCC的更多相关文章
- 【转载】mysql 四种隔离级别分析
sql标准中,有四种隔离级别,各个离级别都有各自的规则,隔离级别越低,允许并发越大,消耗的资源越少,但是越不安全,下面就mysql数据库来分别介绍一下(每个存储引擎实施的隔离级别会有稍微的不同)mys ...
- MySQL 四种隔离级别
什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做. 事务的结束有 ...
- MySql四种隔离级别
什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做. 事务的结束有 ...
- 面试问烂的 MySQL 四种隔离级别,看完吊打面试官!
阅读本文大概需要 5.6 分钟. 来源:网络 什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操 ...
- MySQL 四种隔离级别详解,看完吊打面试官
转发链接:https://zhuanlan.zhihu.com/p/76743929 什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就 ...
- SQL事务的四种隔离级别和MySQL多版本并发控制
SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的那些改变时可见的,那些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销. ReadUncommitted( ...
- 简单理解:数据库的一致性与四种隔离级别(+MySQL实现)
并行数据库存在着几种常见不一致问题: 1.更新丢失:两个并发的写进程同时修改某内容,一个没修改完提交之后另一个又提交,导致其覆盖了第一个提交的写进程内容. 2.脏读:一个操作读到了另外一个操作没有提交 ...
- MySQL面试题--常见的四种隔离级别
什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做. 事务的结束有 ...
- 数据库操作事物的四大特性以及MySQL数据库的四种隔离级别
1 .事物操作数据库的四大特性(ACID) 1.原子性 (Atomicity) 原子性:就是事物的所包含的所有操作,要么全部成功,要么全部失败回滚. 2.一致性 (Consistency) 一致性:简 ...
随机推荐
- Angular使用总结 --- 通过指令动态添加组件
之前自己写的公共组件,都是会先引入,需要调起的时候再通过service控制公共组件状态.值.回调函数什么的.但是有一些场景不适合这种方式,还是动态添加组件更加好.通过写过的一个小组件来总结下. 创建组 ...
- Spark 的 Shuffle过程介绍`
Spark的Shuffle过程介绍 Shuffle Writer Spark丰富了任务类型,有些任务之间数据流转不需要通过Shuffle,但是有些任务之间还是需要通过Shuffle来传递数据,比如wi ...
- javaweb目录结构简介
以上图说明: bbs目录代表一个web应用 bbs目录下的html,jsp文件可以直接被浏览器访问 WEB-INF目录下的资源是不能直接被浏览器访问的 web.xml文件是web程序的主要配置文件 所 ...
- 全网最详细的Eclipse里如何正确新建普通的Java web项目并发布到Tomcat上运行成功【博主强烈推荐】(图文详解)
不多说,直接上干货! 首先,大家要明确,IDEA.Eclipse和MyEclipse等编辑器之间的新建和运行手法是不一样的. 如果是在Myeclipse里,则是File -> new -> ...
- Spring Boot + Spring Cloud 实现权限管理系统 后端篇(十九):服务消费(Ribbon、Feign)
技术背景 上一篇教程中,我们利用Consul注册中心,实现了服务的注册和发现功能,这一篇我们来聊聊服务的调用.单体应用中,代码可以直接依赖,在代码中直接调用即可,但在微服务架构是分布式架构,服务都运行 ...
- MRTG在Windows平台的安装及使用
MRTG (Multi Router Traffic Grapher)是一款监控网络流量负载的免费软件,目前利用MRTG已经开发出了各式各样的统计系统: 1.系统资源负载统计,例如:磁盘空间.CPU负 ...
- go互斥锁Mutex
go mutex是互斥锁,只有Lock和Unlock两个方法,在这两个方法之间的代码不能被多个goroutins同时调用到. 看代码: package main import ( "fmt& ...
- [LeetCode解题报告] 502. IPO
题目描述 假设 LeetCode 即将开始其 IPO.为了以更高的价格将股票卖给风险投资公司,LeetCode希望在 IPO 之前开展一些项目以增加其资本. 由于资源有限,它只能在 IPO 之前完成最 ...
- MySQL事务笔记
1.结束事务的方法用什么? 2.事务的最终形态是什么? commit 提交 rollback 回滚 3.事务的四大特征? ⑴ 原子性 一个事务是最小的工作单元,事务包含的所有操作要么全部成功,要么全部 ...
- c# 正则格式化文本防止SQL注入
/// <summary> /// 格式化文本(防止SQL注入) /// </summary> /// <param name="str">&l ...