谈谈MySQL的事务隔离级别
这篇文章能够阐述清楚跟数据库相关的四个概念:事务、数据库读现象、隔离级别、锁机制
一、事务
先来看下百度百科对数据库事务的定义:
作为单个逻辑单元执行一系列操作,要么完全执行,要么完全不执行。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。
事务有四个属性,称为ACID属性:
1、原子性(Atomicity):事务是一个原子单位,要么全部执行,要么全部不执行。
2、一致性(Consistent):事务的开始和结束,数据都必须保持一致状态。
3、隔离性(isolation):数据库系统提供隔离机制,保证并发事务之间是互相不干扰的。也就意味着事务处理过程中的中间状态对其他的事务是透明的。
4、持久性(Durable):事务完成之后,对数据的修改是永久性的,即使出现系统故障也能够保持。
事务是一系列SQL语句的集合,如果没有事务,会出现什么问题?或者说SQL只能一条一条的单个执行,会出现什么问题?
这个很简单,如果没有事务,我们平时生活中的银行转账就无法操作。
二、数据库读现象
ACID属性里面有一个是隔离级别,即并发事务之间互相不干扰。互相不干扰只是一个终极状态,且需要消耗巨大的性能。在我们实际应用过程中,是存在很大的灰度空间的:隔离级别有程度的区分。所以如果隔离程度控制的比较弱的话,就会产生脏读、不可重复读以及幻读的现象。
1、脏读
事务T1修改某个字段的值,然后事务T2读取该值,此后T1撤销了对该字段的更新,或者更新成另外的值才commit到数据库中,这样T2读取的数据是无效的或者错误的。导致T2依据脏数据所做的操作也是错误的。
思聪同学中午去食堂吃饭,看到窗边的座位被如花同学占有了,思聪认为这个座位已经被占有了,就转身去找其他的座位。不料,如花同学起身离开了。事实是:如花并不是吃饭,而是临时坐在那里等她的约会对象,只是临时小坐一会,并没有真正“commit”。
2、不可重复读
在数据库访问中,一个事务范围内的两次相同的查询却返回了不同的数据。
事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行验证而重新读取,却发现得到了不同的结果。
思聪同学中午去食堂吃饭,看到窗边的座位是空的,便屁颠屁颠的跑去打饭,回来后却发现这个座位被如花同学抢去了。
3、幻读
幻读解决了不可重复读的问题,即在同一个事务范围内,两次相同的查询结果是相同的。但是可以新增表中的数据记录。
幻读是指事务T1对表中的数据进行修改,假设修改涉及了表中全部的数据行,同时第二个事务也修改这个表中的数据,这种修改是向表中插入一条新的数据。后面就会出现操作了T1事务的用户发现表中还有没有修改的数据行,仿佛出现了幻觉一样。
思聪同学中午去食堂吃饭,看到窗边的座位是空的,便屁颠屁颠的跑去打饭,回来后窗边的座位还是空的,便很高兴坐上去准备开始吃饭,这时候却发现如花同学搬了一个小板凳坐在旁边狼吞虎咽,思聪顿时没有了胃口。
如果需要解决脏读、不可重复读、幻读等这些数据库读现象,就必须相应提高事务的隔离级别。但是数据库的隔离级别越高,对应的并发能力就越弱,性能也就相应的越差,所以我们还需根据具体的应用场景去权衡。
三、事务隔离级别
1、未提交读
事务的最低隔离级别,在这种隔离级别下,一个事务可以读取另外一个事务未提交的数据。
数据库锁实现原理:
事务T在读数据的时候并未对数据进行加锁,事务T在修改数据的时候对数据增加行级共享锁
T1在读取数据时,T2可以对相同数据进行读取、修改。因为T1没有进行任何锁操作;当T2对记录进行修改时,T1再次读取数据可以读取到T2修改后的数据。因为T2对数据进行修改只增加了行级共享锁,T1可以再增加共享读锁进行数据读取(尽管T2没有提交事务)
如上所述,这种隔离级别,会导致脏读现象
2、已提交读
在一个事务修改数据过程中,如果事务没有进行提交,其他事务不能读取该数据
数据库锁实现原理:
事务T在读取数据时增加行级共享锁,读取一旦结束,立即释放;事务T在修改数据时增加行级排他锁,直到事务结束才释放。
T1在读取数据的过程中,T2也可以对相同数据进行读取,但是不能进行修改(T1增加的是共享锁,T2也可以增加共享锁,但是不能增加排他锁)。T1读取结束后,会立即释放共享锁,这时T2可以增加排他锁,对数据进行修改,而此时T1既不能对数据进行读取也不能进行修改,直到T2事务结束。
如上所述,这种隔离级别,解决了脏读问题,但是不能解决不可重复读现象。
3、可重复读
事务T在数据读取时,必须增加行级共享锁,直到事务结束;事务T在修改数据过程中,必须增加行级排他锁,直到数据结束。
数据库锁实现原理:
T1在读取数据的过程中,T2也可以对相同数据进行读取,但是不能进行修改(T1增加的是共享锁,T2也可以增加共享锁,但是不能增加排他锁)。直到T1事务结束后,才会释放共享锁,这时T2才可以增加排他锁,对数据进行修改。
如上所述,这种隔离级别,解决了不可重复读现象,但是这种隔离级别解决不了幻读的问题:
T1进行查询,读取了10条记录,并对十条记录增加了行级锁,此时T2是无法对这10行数据进行修改操作的,但是由于没有表级锁,它可以增加一条满足T1查询条件的记录。随后T1在进行查询时,会发现虽然10条记录没有改变,但是突然多了一条记录。
4、序列化
产生幻读是由于没有进行范围查询时没有增加范围锁。
数据库锁实现原理:
事务T在读取数据时,必须先增加表级共享锁,直到事务结束才释放;事务T在修改数据时,必须先增加表级排他锁,直到事务结束才释放。
T1在读取A表时,增加了表级共享锁,此时T2也可以读取A表,但是不能进行任何数据的修改,直到T1事务结束。随后T2可以增加对A表的表级排他锁,此时T1不能读取A表中的任何数据,更不能进行修改。
如上所述,可序列化解决了脏读、不可重复读、幻读等读现象,但是隔离级别越来越高的同时,在并发性上也就越来越低。
四、事务操作实践
默认情况下,MYSQL是自动提交的,也就意味着平时我们执行一条update语句时,MYSQL是自动帮我们提交的,尽快我们没有显示执行commit命令。但是这种只适用于单条SQL的执行。
如果我们想要同时执行多条SQL,并且执行过程中有SQL执行异常,需要回滚前面已经成功执行的SQL或者最终想回滚全部,则必须显示的使用事务。
开始一项事务:start tr ansaction或者begin;
提交事务:commit;
回滚事务:rollback;
事务提交之后的操作:chain;
事务回滚之后的操作:release;
修改当前连接的提交方式:set autocommit;如果设置了set autocommit=0,则设置之后所有的事务都需要显式的通过命令来进行提交或者回滚。
查询当前会话的事务隔离级别

查询当前系统的事务隔离级别

修改当前会话的事务隔离级别

提交读演示
客户端A 开启事务,并更新数据

此时事务还没有提交,开启客户端B,并进行查询,此时的数据还是未更新前的

客户端A进行事务提交,然后客户端B查询,此时是最新的数据

commit and chain的演示
如果在提交的时候使用commit and chain,那么在提交后立即开始一个新的事务

A提交事务后,B再进行查询

开启事务会隐式解锁
锁表期间,用start transaction 命令开始一个新事务,则会隐式的执行unlock tables
A对表进行写锁操作

此时B进行查询:由于被A锁表,所以查询被阻塞

A开启一个事务

由于A开启事务,隐式的释放了写锁,所以B的查询不再被阻塞

SAVEPOINT的使用
事务中可以通过定义SAVEPOINT,指定回滚事务的一个部分
A开启事务并insert一条记录,并设置savepoint

B进行查询,查询到的是开启事务前的数据

A又插入一条数据,然后回滚到savepoint


B进行查询

作者:冬瓜蔡
原文:http://www.cnblogs.com/dongguacai/p/7114885.html
更多Mysql参考内容:http://www.roncoo.com/article/index?tn=Mysql
谈谈MySQL的事务隔离级别的更多相关文章
- MySQL之事务隔离级别--转载
转自:http://793404905.blog.51cto.com/6179428/1615550 本文通过实例展示MySQL事务的四种隔离级别. 1 概念阐述 1)Read Uncommitted ...
- 重新学习MySQL数据库8:MySQL的事务隔离级别实战
重新学习Mysql数据库8:MySQL的事务隔离级别实战 在Mysql中,事务主要有四种隔离级别,今天我们主要是通过示例来比较下,四种隔离级别实际在应用中,会出现什么样的对应现象. Read unco ...
- MySQL实战 | 03 - 谁动了我的数据:浅析MySQL的事务隔离级别
原文链接:这一次,带你搞清楚MySQL的事务隔离级别! 使用过关系型数据库的,应该都事务的概念有所了解,知道事务有 ACID 四个基本属性:原子性(Atomicity).一致性(Consistency ...
- 【MySQL】事务隔离级别及ACID
注:begin或start transaction并不是一个事务的起点,而是在执行它们之后的第一个操作InnoDB表的语句,事务才真正开始.start transaction with consist ...
- 一文读懂MySQL的事务隔离级别及MVCC机制
回顾前文: 一文学会MySQL的explain工具 一文读懂MySQL的索引结构及查询优化 (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论不一定适用于其他版本) 就软件开 ...
- mysql数据库——事务隔离级别
四种隔离级别: 一:READ UNCOMMITTED(未提交读) 事务可以读取其他事务未提交的数据,称为脏读 二:READ COMMITTED(提交读) 一个事务开始时,只能"看见" ...
- 【Java面试】请你简单说一下Mysql的事务隔离级别
一个工作了6年的粉丝,去阿里面试,在第一面的时候被问到"Mysql的事务隔离级别". 他竟然没有回答上来,一直在私信向我诉苦. 我说,你只能怪年轻时候的你,那个时候不够努力导致现在 ...
- MySQL数据库事务隔离级别(Transaction Isolation Level)
转自: http://www.cnblogs.com/zemliu/archive/2012/06/17/2552301.html 数据库隔离级别有四种,应用<高性能mysql>一书中的 ...
- 浅谈MySQL的事务隔离级别
希望这篇文章能够阐述清楚跟数据库相关的四个概念:事务.数据库读现象.隔离级别.锁机制 一.事务 先来看下百度百科对数据库事务的定义: 作为单个逻辑单元执行一系列操作,要么完全执行,要么完全不执行.事务 ...
随机推荐
- PhpStorm的破解 汉化
以前一直习惯使用sublime,最近发现phpstorm比submit稍微更强大些,其很多插件都是直接可以使用,不需要另外去拓展了 其中的破解.汉化步骤就需要借助一些资源 (1)破解 安装完毕后,直接 ...
- Trie树 字典树-学习笔记
字符串--蒟蒻永远的阴影 对于字符串匹配 KMP很好的解决了以一个文本串匹配一个模板串的问题 但如果模板串有多个呢 这是KMP不再适用 我们引入一个新的数据结构--字典树 (当然又有像AC自动机这样更 ...
- JAVA受检异常和非受检异常举例
受检异常和非受检异常(运行时异常)举例 RuntimeException(即非受检异常): RuntimeException在默认情况下会得到自动处理,所以通常用不着捕获RuntimeExceptio ...
- Spring-Security自定义登录页&inMemoryAuthentication验证
Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架.框架下内容比较多,可以做到按照角色权限对请求路径进行限制.今天主要验证自定义登录页,在内存用户存储中进行请求 ...
- linux中/bin和/sbin和/usr/bin和/usr/sbin
首先先解释一下bin和sbin的意思: 1.bin:为任何用户都可以使用的指令 2.sbin:(super bin)也就是只有超级管理员才能使用的指令 /usr UNIX Software Re ...
- C语言_指针和数组的几种访问形式
敲几行代码来看看几种访问的形式~ #include <stdio.h>;int main() { ] = {, , , , , }; //初始化5个元素的一维数组 int *p = arr ...
- HDU - 4496 City 逆向并查集
思路:逆向并查集,逆向加入每一条边即可.在获取联通块数量的时候,直接判断新加入的边是否合并了两个集合,如果合并了说明联通块会减少一个,否则不变. AC代码 #include <cstdio> ...
- UVA1619 栈维护递增序列
先说这题的关键性质:每一个数应该只会计算一次,它有一个最小区间[L,R],即它在这个区间内是最小的,最小区间内任何包含它的子区间都不会大于F(L,R)=(a[L]+...+a[R])*min(a[l] ...
- Zookeeper笔记1-CAP/BASE理论
分布式系统八大谬论: 1.网络相当可靠 2.延迟为0 3.传输带宽是无限的 4.网络相当安全. 5.拓扑结构不会改变 6.必须要有一名管理员 7.传输成本为0 8.网络同质化. 分布式最常出现的问题: ...
- Linux socket网络编程基础 tcp和udp
Socket TCP网络通信编程 首先,服务器端需要做以下准备工作: (1)调用socket()函数.建立socket对象,指定通信协议. (2)调用bind()函数.将创建的socket对象与当前主 ...