MySQL 4 种隔离级别的区别
## 测试环境
mysql> select version();
+------------+
| version() |
+------------+
| 5.7.11-log |
+------------+
数据库事务特性 ACID,即
A(Atomicity) -原子性
C(Consistency)- 一致性
I(Isolation) - 隔离性
D(Durability) - 持久性
MySQL 提供了 4 种不同的隔离级别,用来支持多版本并发控制(MVCC,Multi-Version Concurrency Control)。
默认的事务隔离级别是 REPEATABLE-READ(可重读):
mysql> select @@global.tx_isolation, @@session.tx_isolation;
+-------------------------+---------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-------------------------+---------------------------+
| REPEATABLE-READ | REPEATABLE-READ |
+-------------------------+---------------------------+
在该事务级别下,一个事务期间内,该事务不考虑其他提交语句。
0x00、测试准备
1. 创建测试表
mysql> CREATE TABLE `transaction_test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`val` varchar(20) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
2. 开启两个 MySQL 客户端进行测试
0x01、REPEATABLE-READ(可重读)
step 1:
在 Client 1 下开启事务,查询测试表中的数据:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
Empty set (0.00 sec)
step 2:
在 Client 2 下开启事务,并且往测试表中插入数据,但不提交事务:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> insert into transaction_test (val) values ('x'),('y'),('z');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | x | 2017-02-06 00:20:59 |
| 2 | y | 2017-02-06 00:20:59 |
| 3 | z | 2017-02-06 00:20:59 |
+----+-----+---------------------+
3 rows in set (0.00 sec)
step 3:
在 Client 1 下查看表中数据:
mysql> select * from transaction_test;
Empty set (0.00 sec)
仍然是空表。
step 4:
Client 2 提交事务:
mysql> commit;
Query OK, 0 rows affected (0.12 sec)
step 5:
Client 1 下查看表中数据:
mysql> select * from transaction_test;
Empty set (0.00 sec)
任然是空表。
step 6:
Client 1 提交事务,查看表中数据:
mysql> commit;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | x | 2017-02-06 00:20:59 |
| 2 | y | 2017-02-06 00:20:59 |
| 3 | z | 2017-02-06 00:20:59 |
+----+-----+---------------------+
3 rows in set (0.00 sec)
当 Client 1 完成事务后,才能看到其他事务提交的数据。
0x02、READ-COMMITTED(读取提交内容)
step 1:
Client 1 中清空表,改变数据库隔离级别:
mysql> truncate table transaction_test;
Query OK, 0 rows affected (0.10 sec) mysql> set @@session.tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec) mysql> select @@global.tx_isolation, @@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| REPEATABLE-READ | READ-COMMITTED |
+-----------------------+------------------------+
1 row in set (0.00 sec)
step 2:
Client 1 开启事务,查询表中数据:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
Empty set (0.00 sec)
step 3:
Client 2 开启事务,向表中插入数据,但不提交事务:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> insert into transaction_test (val) values ('x'),('y'),('z');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | x | 2017-02-06 00:31:00 |
| 2 | y | 2017-02-06 00:31:00 |
| 3 | z | 2017-02-06 00:31:00 |
+----+-----+---------------------+
3 rows in set (0.00 sec)
step 4:
Client 1 下查看表中数据:
mysql> select * from transaction_test;
Empty set (0.00 sec)
仍然是空表。
step 5:
Client 2 提交事务:
mysql> commit;
Query OK, 0 rows affected (0.13 sec)
step 6:
Client 1 下查看表中数据:
mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | x | 2017-02-06 00:31:00 |
| 2 | y | 2017-02-06 00:31:00 |
| 3 | z | 2017-02-06 00:31:00 |
+----+-----+---------------------+
3 rows in set (0.00 sec)
与 REPEATABLE-READ 不同的是,Client 1 没有结束事务也能看到其他事务提交的数据。
0x03、READ-UNCOMMITTED(读取未提交内容)
step 1:
Client 1 下清空表,设置隔离级别:
mysql> truncate table transaction_test;
Query OK, 0 rows affected (0.10 sec) mysql> set @@session.tx_isolation = 'READ-UNCOMMITTED';
Query OK, 0 rows affected (0.00 sec) mysql> select @@global.tx_isolation, @@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| REPEATABLE-READ | READ-UNCOMMITTED |
+-----------------------+------------------------+
1 row in set (0.00 sec)
step 2:
Client 1 下开启事务,查询表数据:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
Empty set (0.00 sec)
step 3:
Client 2 下开启事务,向表中插入数据,但是不提交事务:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> insert into transaction_test (val) values ('x'),('y'),('z');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | x | 2017-02-06 00:43:59 |
| 2 | y | 2017-02-06 00:43:59 |
| 3 | z | 2017-02-06 00:43:59 |
+----+-----+---------------------+
3 rows in set (0.00 sec)
step 4:
Client 1 中查询数据:
mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | x | 2017-02-06 00:43:59 |
| 2 | y | 2017-02-06 00:43:59 |
| 3 | z | 2017-02-06 00:43:59 |
+----+-----+---------------------+
3 rows in set (0.00 sec)
与 READ-COMMITTED 不同的是,在 Client 2 不提交事务的情况下,Client 1 也能读到其他事务插入的数据,即脏数据或者说产生了“脏读”。在一个事务期间读到了另一个事务在未提交之前产生的数据,那么第一个事务就读到了脏数据,产生了对第二个事务未提交数据的依赖,如果第二个事务回滚,那么第一个事务读到的数据是错误的脏数据。
“脏读”与“幻读”、“不可重复读”的区别是:幻读是读取结果集条数的对比,一个事务按相同的查询条件查询之前检索过的数据,发现检索出来的结果集条数变多或者减少(由其他事务插入、删除的),类似产生幻觉。
不可重复读是读取的数据本身的对比,一个事务在读取某些数据后的一段时间后,再次读取这个数据,发现其读取出来的数据内容已经发生了改变,就是不可重复读。
step 5:
Client 2 回滚事务:
mysql> rollback;
Query OK, 0 rows affected (0.04 sec) mysql> select * from transaction_test;
Empty set (0.00 sec)
step 6:
Client 1 查询表数据:
mysql> select * from transaction_test;
Empty set (0.00 sec)
空表。
0x04、SERIALIZABLE(序列化)
step 1:
Client 1 下清空表,设置隔离级别:
mysql> truncate table transaction_test;
Query OK, 0 rows affected (0.21 sec) mysql> set @@session.tx_isolation ='SERIALIZABLE';
Query OK, 0 rows affected (0.00 sec) mysql> select @@global.tx_isolation, @@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| REPEATABLE-READ | SERIALIZABLE |
+-----------------------+------------------------+
1 row in set (0.00 sec)
step 2:
Client 1 开启事务,查询表:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
Empty set (0.00 sec)
step 3:
Client 2 开启事务,向表中插入数据:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> insert into transaction_test (val) values ('x'),('y'),('z');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
此时 Client 2 插入数据(INSERT 操作)会被阻塞,直到第一个(Client 1)事务提交后,Client 2 的插入操作才能完成。
step 4:
Client 1 提交事务:
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
step 5:
Client 2 插入数据:
mysql> insert into transaction_test (val) values ('x'),('y'),('z');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 4 | x | 2017-02-06 00:54:17 |
| 5 | y | 2017-02-06 00:54:17 |
| 6 | z | 2017-02-06 00:54:17 |
+----+-----+---------------------+
3 rows in set (0.00 sec)
参考:
[MySQL]对于事务并发处理带来的问题,脏读、不可重复读、幻读的理解
MySQL 4 种隔离级别的区别的更多相关文章
- MySQL两种引擎的区别
Innodb引擎 Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别.该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL ...
- Mysql 两种引擎的区别
MyISAM与InnoDB的区别是什么? 1. 存储结构 MyISAM:每个MyISAM在磁盘上存储成三个文件.第一个文件的名字以表的名字开始,扩展名指出文件类型..frm文件存储表定义.数据文件的扩 ...
- mysql几种连接方式区别
mysql的几种join 2017年03月19日 14:49:07 carl-zhao 阅读数:7845 标签: mysqlsqljoin 更多 个人分类: MySQL 版权声明:本文为博主原创文章, ...
- mysql几种关联的区别
1.平时都是用的逗号的模式:select * from a,b where a.id=b.id,逗号的模式等于inner join和join: 2.left join 和 right join相反,效 ...
- MySQL ACID及四种隔离级别的解释
以下内容出自<高性能MySQL>第三版,了解事务的ACID及四种隔离级有助于我们更好的理解事务运作. 下面举一个银行应用是解释事务必要性的一个经典例子.假如一个银行的数据库有两张表:支票表 ...
- [转]Mysql几种索引类型的区别及适用情况
此为转载文章,仅做记录使用,方便日后查看,原文链接:https://www.cnblogs.com/yuan-shuai/p/3225417.html Mysql几种索引类型的区别及适用情况 如大 ...
- MySQL中四种隔离级别的演示
事务的隔离是并发操作中需要理解清楚的问题.MySQL中共有4种不同的隔离级别,这4种隔离级别分别是: 隔离级别类型 影响结果 READ UNCOMMITTED(未提交读) 事务将会读取到未提交的数据, ...
- MySQL数据库引擎介绍、区别、创建和性能测试的深入分析
本篇文章是对MySQL数据库引擎介绍.区别.创建和性能测试进行了详细的分析介绍,需要的朋友参考下 数据库引擎介绍 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎 ...
- [转]MySQL数据库引擎介绍、区别、创建和性能测试的深入分析
本篇文章是对MySQL数据库引擎介绍.区别.创建和性能测试进行了详细的分析介绍,需要的朋友参考下 数据库引擎介绍 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎 ...
随机推荐
- Kafka、RabbitMQ、RocketMQ等消息中间件的对比 —— 消息发送性能和区别
https://blog.csdn.net/yunfeng482/article/details/72856762
- JAVA中handleEvent和action的区别
看代码中用到了handleEvent和action,都是对事件进行处理的,觉得这两个方法可以直接合并,于是尝试合并后,发现功能还是有问题,说明两者还是有区别了,查了很久的资料,才基本了解这两者的区别. ...
- C#多线程编程实战(二)
1.1 简介 为了防止一个应用程序控制CPU而导致其他应用程序和操作系统本身永远被挂起这一可能情况,操作系统不得不使用某种方式将物理计算分割为一些虚拟的进程,并给予每个执行程序一定量的计算能力.此外操 ...
- XamarinEssentials教程获取首选项的值
XamarinEssentials教程获取首选项的值 如果开发者想要获取首选项中某一项的值时,可以使用Preferences类的Get()方法实现,该方法可以对指定键的值进行获取.该方法有12种形式, ...
- 小型资源管理器之动态添加TreeView节点
FrmMain主界面 using System; using System.Collections.Generic; using System.ComponentModel; using System ...
- 网络测试工具 - QCheck
本片博客内容借鉴51CTO中joyssue博主文章. 网络性能不仅与交换和路由设备的性能相关,而且与线路质量也有很大关系.使用Qcheck可以测试网络性能.这是NetIQ公司开发的一款免费网络测试软件 ...
- win7生成ssh key配置到gitlab
测试服务上使用ip访问gitlab,比如http://192.168.0.2/,创建用户并登陆后创建一个项目,比如git@gitlab.demo.com:demo/helloworld.git 如果想 ...
- 3ds max学习笔记(八)-- 实例操作(直行楼梯)
1.选择要复制的物体,执行[工具]/[阵列]命令,弹出对话框: 2.参数说明: 应用: 1.[自定义]/[单位设置],将单位改为mm 在顶视图中,创建长方体,长1600,宽300,高度150 2.在前 ...
- Node_初步了解(3)回调,作用域,上下文
1. //回调:回调是异步编程最基本的方法,node.js需要按顺序执行异步逻辑的时候,一般采用后续传递的方式,将后续逻辑封装在回调函数中,作为起始函数的参数. //具名函数 function lea ...
- nodeJs --- web服务器创建
一.下载nodeJs http://nodejs.cn/download/ 根据自己的情况选择下载 然后在命令行中输入 node -v 看是否安装成功 (下载node时,会把npm包处理工具一起下) ...