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) 一致性:简 ...
随机推荐
- 实现instanceof关键字
如果用Java的伪代码来表现Java语言规范所描述的运行时语义,会是这样: // obj instanceof T boolean result; if (obj == null) { result ...
- Maven - 实例-1-手工创建Maven项目
1- 根据包结构创建maven项目目录 TestMaven - src - src/main/java/anliven/testmaven01/HelloMaven.java - src/test/j ...
- .NET手记-友盟消息推送服务器端加密算法的实现
最近为App开发消息推送功能,这里我们采用了友盟的消息推送服务,但其后台简陋,可定制化程度低,所以决定接入服务器端API,在自己的服务器上部署一套推送服务. 其中涉及到很多问题,首先要解决的就是与友盟 ...
- python tricks
1. cities = ['Marseille', 'Amsterdam', 'New York', 'Londom'] # the good way for i, city in enumerate ...
- redis epoll 原理梗概
redis 是一个单线程却性能非常好的内存数据库, 主要用来作为缓存系统. redis 采用网络IO多路复用技术来保证在多连接的时候, 系统的高吞吐量.为什么 Redis 中要使用 I/O 多路复用这 ...
- Webpack代理proxy配置,解决本地跨域调试问题,同时允许绑定host域名调试
Webpack代理proxy配置,解决本地跨域调试问题,同时允许绑定host域名调试 会撸码的小马 关注 2018.05.29 17:30* 字数 212 阅读 1488评论 0喜欢 2 接到上一章, ...
- Python3学习笔记 - day1
前言 本文不是一篇系统的从零开始学习Python的教程,如果你需要从零开始学习Python,廖雪峰的官方网站中Python教程这部分将是比较好的一种选择,如果你英语比较好,也可以在国外的一些网站上找到 ...
- 开启python学习之路
新生入学这一周来,基本都在看python从入门到精通,边看书边敲代码,简单的几行代码,巩固学到的知识,像当初学习各类编程语言一样,从最初开发环境的搭建,数据类型等,学习中做好笔记,然后学会运用. 学习 ...
- go map的使用
欢迎关注go语言微信公众号 每日go语言 golang_everyday go中map用于存储健值对.map格式: map[KeyType]ValueType 声明一个map,键为字符型,值为int型 ...
- jquery插入,复制、替换和删除节点
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...