Mysql隔离级别 sql示例理解
前言
事务要解决的是多线程并发修改数据库的问题。Mysql innodb 引擎支持事务。类似 Java 中的各种锁,例如乐观锁(CAS),读写锁,悲观锁。事务也有很多级别。
每个隔离级别要解决的问题都是不同的。
一张表格来看看 Spring 事务每个隔离级别能够解决的问题。。

再说说脏读,不可重复读,幻读的解释。
脏读场景: 1.事务 A 读取数据 2.事务 B 修改数据(未提交) 3.事务 A 读取数据已和第一次读的不同
不可重复读场景: 1.事务 A 读取数据 2.事务 B 修改数据(提交) 3.事务 A 读取数据已和第一次读的不同
幻读场景: 1.事务 A 读取数据 2.事务 B 新增数据 3.事务 A 再次读取数据已和第一次不同
再解释一下 4 个隔离级别:
- 未提交读:表示另一个事务修改了数据,还没有提交,这个事务就可以读到了。
- 已提交读:表示另一个事务修改了数据,同时提交了,这个事务就可以读到了,如果没提交,就读不到。
- 可重复读:表示另一个事务即使修改了数据(已提交),这个事务也是看不到的,因此这个事务每次读到的数据都是一样的。这叫可重复读。
- 可串行化:可以想象成 Java 语言的锁。一个个执行。毫无并发性。性能令人发指。
其中关于可重复读需要解释一下在 mysql 场景下的幻读问题,按照标准,可重复读应该会导致幻读,但 mysql 如果在一个事务中,第二次读取的数据使用的是第一次的结果,因此不会产生幻读。
关于默认的级别,很多文章说是 “已提交读”,但经过详细的测试,应该是可重复读。
因此,大部分时候,使用默认的级别,就能得到和串行化相同的目的。而串行的成本则是非常的高昂,类似悲观锁。还有一点,mysql 的事务是借助行锁来实现的。
above from : http://thinkinjava.cn/2018/05/Spring-%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1-%E4%B8%80-%E9%9A%94%E7%A6%BB%E5%B1%9E%E6%80%A7/
under from: www.jianshu.com/p/db334404d909
一、Mysql的四个隔离级别
预备工作:
先创建一个test数据库及account表
create database test;
use test;
create table account(
id int not null,
balance float not null,
PRIMARY KEY ( id)
)
INSERT INTO table(id,balance)
VALUES (1,1000);
INSERT INTO table(id,balance)
VALUES (2,1000);
开启两个控制台窗口,当做两个用户(A和B)
1.1. read unCommited (未提交读)
也即RU,在READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)。这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。
A用户操作如下:
set session transaction isolation level read uncommitted;
start transaction;
select * from account;
结果如下:
id balance
1 1000
2 1000
B用户操作如下:
set session transaction isolation level read uncommitted;
start transaction;
update account set balance=balance+200 where id = 1;
随后在A用户终端中查询数据,结果如下:
id balance
1 1200
2 1000
可以看到B用户并未提交事务,但是A用户却能读到未提交的数据,这就是脏读。
1.2. read commited (提交读)
即RC,大多数数据库系统为了避免 脏读 采用的默认隔离级别都是read commited(但MySQL不是,Mysql的默认隔离级别是repeatable read )。
READ COMMITTED满足前面提到的隔离性的简单定义:一个事务开始时,只能”看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。
这个级别有时候叫做不可重复读(nonrepeatble read),因为两次执行同样的查询,可能会得到不一样的结果。以例子说明:
我们将用户B所在的会话当前事务隔离级别设置为read commited。
set session transaction isolation level read committed;
在A所在的会话中执行
update account set balance=balance-200 where id = 1;
在B用户的会话中查询:
select * from account;
结果如下:
id balance
1 1000
2 1000
发现数据没有变,还是1000,说明可以避免脏读了。
接着A用户会话中将事务提交:
commit;
再次在B中查询,结果如下:
id balance
1 800
2 1000
可以看到,B用户读取到了A用户提交的数据。这么做有什么问题么?那就是我们在会话B同一个事务中,读取到两次不同的结果。这就造成了不可重复读,就是两次读取的结果不同。
1.3 . repeatable read(可重复读)
REPEATABLE READ解决了脏读的问题。该隔离级别保证了在同一个事务中多次读取同样记录结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom Read)的问题。
所谓 幻读,指的是当某个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。
Mysql的RR是由“行排它锁+MVCC”一起实现的。
我们将用户B所在的会话当前事务隔离级别设置为repeatable read。
set session transaction isolation level repeatable read;
start transaction;
接着在B中查询数据:
id balance
1 1000
2 1000
两条。
然后我们到A用户会话中插入一条数据:
insert into account(id,balance) value(3,1000);
在A中查看是否添加成功:
————————————————————————
insert into account(id, balance) value (3, 1000);
select * from account;
id balance
1 1000
2 1000
3 1000
————————————————————————
成功,有三条数据。
回到用户B会话中,再次查询:
id balance
1 1000
2 1000
发现没有变还是两条。这时,用户B想插入一条id=3,balance=1000的数据:
insert into account(id,balance) value(3,1000);
会报错:
————————————————————————————————
mysql> insert into account(id,balance) value(3,1000);
ERROR 1062(23000): Duplicate entry '3' for key 'primary'
mysql>
————————————————————————————————
说是主键重复了,可是B用户刚刚查询并没有id=3的记录。这就是幻读现象。
我的理解是:不可重复读指的是update操作,而幻读指的是insert或delete操作。
1.4 SERIALIZABLE(串行化)
SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取每一行数据都加锁,所以可能导致大量的超时和锁争用问题。
实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。
Mysql隔离级别 sql示例理解的更多相关文章
- SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...
- ★ MYSQL隔离级别 通俗理解 + mysql、oracle默认事务隔离级别
★ 脏读 : 读取了前一事务 未提交 的数据 ; 不可重复读 : 读取了前一事务 提交 的数据: ★ 幻读 与 不可重复读 common :都是读取了另一条已经提交的事务(这点与脏读不 ...
- mysql 隔离级别与间隙锁等
数据库隔离级 SQL标准中DB隔离级别有: read uncommitted:可以读到其它transaction 未提交数据 read committed:可以读到其它transaction 已提交数 ...
- 详解MySQL隔离级别
一个事务具有ACID特性,也就是(Atomicity.Consistency.Isolation.Durability,即原子性.一致性.隔离性.持久性),本文主要讲解一下其中的Isolation,也 ...
- Mysql隔离级别,锁与MVCC
关键词:事务,ACID,隔离级别,MVCC,共享锁,排它锁 阅读本文前请先阅读http://hedengcheng.com/?p=771 http://www.hollischuang.com/arc ...
- mysql事务之二:MySQL隔离级别演示
登录mysql: mysql -u root -p123456 Mysql 版本号 mysql> select version(); +-------------------------+ | ...
- mysql隔离级别与锁,接口并发响应速度的关系(2)
innoDB默认隔离级别 mysql> SELECT @@tx_isolation; +-----------------+ | @@tx_isolation | +-------------- ...
- 设置mysql隔离级别
1.查看当前会话隔离级别 select @@tx_isolation; 2.查看系统当前隔离级别 select @@global.tx_isolation; 3.设置当前会话隔离级别 set sess ...
- 事务与Mysql隔离级别
事务 定义: 比如ABCD四个业务,作为一个事务,他们要么一起都执行完毕,要么都不执行.(只要有一个不成功,那么所有的都不可以成功) 四个特性 ACID 原子性(Atomicity) 整个事务中的所有 ...
随机推荐
- 解决dos窗口乱码问题
大家有没有遇到这样的情况,看着就糟心 打开dos窗口, 输入命令 chcp 936 (936表示中文编码GBK, 也可以设置其他编码), 回车一下执行. 鼠标右键 -> 属性 (关键一步): ...
- 显示Unicode 字节的对应字符的小技巧
在一段smali代码里看到这样的代码 const-string v0, "\u7528\u6237\u9a8c\u8bc1\u8fc7\u671f\uff0c\u8bf7\u91cd\u65 ...
- 雷林鹏分享:C# 不安全代码
C# 不安全代码 当一个代码块使用 unsafe 修饰符标记时,C# 允许在函数中使用指针变量.不安全代码或非托管代码是指使用了指针变量的代码块. 指针变量 指针 是值为另一个变量的地址的变量,即,内 ...
- Silverlight自定义控件系列 – TreeView (3) 添加展开和收起事件
由于Writer嫌我文章过长,只能把上篇拆开两半了.以下是接着上篇的. 准备工作做完了,现在就要完成点击事件. 定义Expander和单击事件: 1: /// <summary> 2: / ...
- php--------获取当前时间、时间戳
首先需要知道的是在php中获取时间方法是date(),在php中获取时间戳方法有time().strtotime().下面分别说明. date() 格式为:date($format, $timesta ...
- 百度安卓SDK秘钥Key错误
下载官方安卓地图demo,输入报名和sha1申请AK,发现key错误 构建的时候要指定生成的key 安卓定位BaiduLocDemo出现aapt.exe finished with non-zero ...
- hdu 2018多校8
A.Character Encoding 简单计数 m个非负数和等于k的方案数为$\binom{m+k-1}{k}$, 但题目还要求每个数小于n, 容斥一下即可 即$ans = \sum\limits ...
- Python基础--文件操作和集合
这篇博客来说一下python对文件的操作. 对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句柄操作文件 3.关闭文件. 现有以下文件file.txt: 我们哭了 ...
- C# 中的时间(DataTime)
在做报表或查询的时候,常常会预设一些可选的日期范围,如本周.本月.本年等,利用 C# 内置的DateTime基本上都可以实现这些功能. 当前时间: DateTime dt = DateTime.Now ...
- Ajax中Delete请求参数 后台无法获取的解决方法(Restful风格)
方法一: 在ajax中写入data来传参时,直接把参数拼接到url后面 例如: $.ajax({ url: '/cyberspace/vrv/event/delete/1002?startTime=& ...