## 测试环境
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 种隔离级别的区别的更多相关文章

  1. MySQL两种引擎的区别

    Innodb引擎 Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别.该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL ...

  2. Mysql 两种引擎的区别

    MyISAM与InnoDB的区别是什么? 1. 存储结构 MyISAM:每个MyISAM在磁盘上存储成三个文件.第一个文件的名字以表的名字开始,扩展名指出文件类型..frm文件存储表定义.数据文件的扩 ...

  3. mysql几种连接方式区别

    mysql的几种join 2017年03月19日 14:49:07 carl-zhao 阅读数:7845 标签: mysqlsqljoin 更多 个人分类: MySQL 版权声明:本文为博主原创文章, ...

  4. mysql几种关联的区别

    1.平时都是用的逗号的模式:select * from a,b where a.id=b.id,逗号的模式等于inner join和join: 2.left join 和 right join相反,效 ...

  5. MySQL ACID及四种隔离级别的解释

    以下内容出自<高性能MySQL>第三版,了解事务的ACID及四种隔离级有助于我们更好的理解事务运作. 下面举一个银行应用是解释事务必要性的一个经典例子.假如一个银行的数据库有两张表:支票表 ...

  6. [转]Mysql几种索引类型的区别及适用情况

    此为转载文章,仅做记录使用,方便日后查看,原文链接:https://www.cnblogs.com/yuan-shuai/p/3225417.html Mysql几种索引类型的区别及适用情况   如大 ...

  7. MySQL中四种隔离级别的演示

    事务的隔离是并发操作中需要理解清楚的问题.MySQL中共有4种不同的隔离级别,这4种隔离级别分别是: 隔离级别类型 影响结果 READ UNCOMMITTED(未提交读) 事务将会读取到未提交的数据, ...

  8. MySQL数据库引擎介绍、区别、创建和性能测试的深入分析

    本篇文章是对MySQL数据库引擎介绍.区别.创建和性能测试进行了详细的分析介绍,需要的朋友参考下   数据库引擎介绍 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎 ...

  9. [转]MySQL数据库引擎介绍、区别、创建和性能测试的深入分析

    本篇文章是对MySQL数据库引擎介绍.区别.创建和性能测试进行了详细的分析介绍,需要的朋友参考下   数据库引擎介绍 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎 ...

随机推荐

  1. thinkpad那些事儿

    之前玩过windows系统的acer笔记本,联想台式机,os系统的mac pro笔记本,最近刚接触windows系统的thinkpad笔记本,对它的键盘触感印象深刻,舒服.thinkpad,思考本,是 ...

  2. angular笔记_1

    第一个angular文件<script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js&q ...

  3. Django之ORM字段和字段参数

    ORM介绍 ORM概念 ORM由来 ORM的优势 ORM的劣势 ORM总结 Django中的ORM Django项目使用MySQL数据库 Model 快速入门 字段 自定义字段 字段参数 Model ...

  4. AE插入音乐

    将音乐文件(如MP3文件)直接拖拽到工程里就可以. 然后添加到合成里. 点击内容预览 ,就自动播放了. 在合成窗口里面,我们可以对于音频文件进行拖动,以及裁剪等操作,但是需要注意的是AE里面不能预览声 ...

  5. [CSAcademy]Sum of Powers

    [CSAcademy]Sum of Powers 题目大意: 给定\(n,m,k(n,m,k\le4096)\).一个无序可重集\(A\)为合法的,当且仅当\(|A|=m\)且\(\sum A_i=n ...

  6. IDEA中maven模块变成灰色

    可能该模块被忽略,解决办法:

  7. [P1441]砝码称重 (搜索+DP)

    对于我这种蒟蒻,是很不错的一题了. dfs搜索当前状态 满足时DP 比较坑的地方就是起始的地方 我一开始从1开始,搜索写的是从0开始. 后来就统一用0开始的了. #include<bits/st ...

  8. ubuntu下用nvm配置好nodejs环境

    cd ~mkdir .gitcd .gitgit clone https://github.com/creationix/nvm.git 这样先把nvm下载过来,然后安装 ./install.sh c ...

  9. C++程序设计方法3:强制类型转换

    强制类型转换(显示转换) dynamic_cast<Dst_Type>(Src_var) Src_var必须是引用或者指针类型,Dst_Type类中含有虚函数,否则会有编译错误: 若目标类 ...

  10. 疫情控制 [NOIP2012]

    Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫 ...