MySQL中四种隔离级别的演示

事务的隔离是并发操作中需要理解清楚的问题.MySQL中共有4种不同的隔离级别,这4种隔离级别分别是:

隔离级别类型 影响结果
READ UNCOMMITTED(未提交读) 事务将会读取到未提交的数据,可能会造成脏读、可重复读和幻读的现象,是一种较低的隔离级别,在实际中较少使用
READ COMMITTED(提交读) 该种隔离级别在事务1没有提交或回滚时,事务2可避免脏读,但是在事务1提交或回滚之后,事务2出现了可重复读和幻读的情况
REPEATABLE READ(可重复读) 可重复读是MySQL默认的隔离级别,可以有效避免脏读和可重复读的情况,但是不能避免幻读
SERIABLIZABLE(串行化)  可以同时解决脏读、可重复读和幻读的情况,但是由于会出现阻塞的情况,所以实际中也较少使用

可以看出,不同的隔离级别有不同的多事务执行结果。MySQL中的InnoDB存储引擎的默认的隔离级别是可重复读(REPEATABLE READ).

本文使用演示了上表中所列出的4种隔离级别(基于MySQL5.7).使用的表为test,test中的字段分别是id、name.

mysql> select * from test;
+------+-------+
| id   | name  |
+------+-------+
|  100 | zhangsan |
|  200 | lisi  |
+------+-------+

由于MySQL中默认开启的是隐式事务,所以为了操作的效果不受影响,需要将事务开启成显式的.同时启动了两个会话窗口,并将启动的两个会话窗口都需要如此操作.在第一个窗口执行:

mysql> set autocommit=0;

1、READ UNCOMMITTED

由下面的查询结果可以看出,MySQL中默认的隔离级别为REPEATABLE READ:

mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+

因此需要将默认的隔离级别设置为READ UNCOMMITED:

mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Query OK, 0 rows affected (0.00 sec)

(1)在第一个窗口执行:

mysql> UPDATE test SET name=‘wangwu‘ WHERE id=100;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

(2)在第二个窗口中查询test表: 

mysql> SELECT * FROM test;
+------+--------+
| id   | name   |
+------+--------+
|  100 | wangwu |
|  200 | lisi   |
+------+--------+
2 rows in set (0.00 sec)

从上面的输出结果中可以看出,id=100对应的name为wangwu.

(3)接着在第一个窗口中执行ROLLBACK操作,再次在第二个窗口查询时,id=100对应的name为zhangsan,说明了READ UNCOMMITTED隔离级别不可避免脏读.这里没有测试可重读读和幻读的情况了,因为如果脏读没有避免,那么也会出现可重复读和幻读的情况.

mysql> select * from test;
+------+----------+
| id   | name     |
+------+----------+
|  100 | zhangsan |
|  200 | lisi     |
+------+----------+
2 rows in set (0.00 sec)

  

2、READ COMMITTED

将第一个和第二个窗口的隔离级别都设置为:

mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)

在第一个窗口重新开启一个事务:

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

接着在第一个窗口执行(此时没有进行commit或rollback操作):

mysql> update test set name=‘wangwu‘ where id=100;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

  

在第二个窗口中查询test:

mysql> select * from test;
+------+----------+
| id   | name     |
+------+----------+
|  100 | zhangsan |
|  200 | lisi     |
+------+----------+
2 rows in set (0.00 sec)

  

通过上面的输出结果可知,使用了READ COMMITTED隔离级别后,没有出现脏读的情况。但是当在窗口一中执行commit时,从窗口二中查询得到的结果已经发生改变:

mysql> select * from test;
+------+--------+
| id   | name   |
+------+--------+
|  100 | wangwu |
|  200 | lisi   |
+------+--------+
2 rows in set (0.00 sec)

  

从而可知,提交前和提交后得到的两种情况不相同,从而说明了READ COMMITTED不能避免可重复读。

3、REPEATABLE READ

开始前的数据:

mysql> select * from test;
+------+----------+
| id   | name     |
+------+----------+
|  100 | zhangsan |
|  200 | lisi     |
+------+----------+
2 rows in set (0.00 sec)

同样的,将第一个和第二个窗口的隔离级别都设置为:

mysql> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)

第一个窗口执行:

mysql> SET AUTOCOMMIT=0;
Query OK, 0 rows affected (0.00 sec)

在第一个窗口更新test中的name:

mysql> UPDATE test set name=‘xiaoming‘ where id=100;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

在第二个窗口查询test:

mysql> select * from test;
+------+----------+
| id   | name     |
+------+----------+
|  100 | zhangsan |
|  200 | lisi     |
+------+----------+
2 rows in set (0.00 sec)

此时发现,在第二个窗口中查询的数据并没有发生改变,REPEATABLE READ可以避免脏读。

同时,当第一个窗口提交更新后,在第二个窗口中执行查询时,数据没有发生变化,说明此时也避免了可重复读的情况。

mysql> select * from test;
+------+----------+
| id   | name     |
+------+----------+
|  100 | zhangsan |
|  200 | lisi     |
+------+----------+
2 rows in set (0.00 sec)

在第二个窗口中无论读取多少次,读取到的数据都不会是第一个窗口中更新的数据,只有当第二个窗口也提交时,此时的第二个窗口才会更新数据。

mysql> select * from test;
+------+----------+
| id   | name     |
+------+----------+
|  100 | xiaoming |
|  200 | lisi     |
+------+----------+
2 rows in set (0.00 sec)

最后,在第二个窗口插入一条数据:

mysql> insert into test values(300,‘wangwu‘);
Query OK, 1 row affected (0.00 sec)

在第一个窗口更新数据,按道理来说,应该会有两行数据受影响,但是此时发现有三行数据受影响了,说明了出现了幻读的现象:

mysql> update test set name=‘zhaoliu‘;
Query OK, 3 rows affected (6.36 sec)
Rows matched: 3  Changed: 3  Warnings: 0

4、 SERIALIZABLE

将第一个和第二个窗口的隔离级别都设置为:

mysql> SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Query OK, 0 rows affected (0.00 sec)

开始操作前的数据:

+------+---------+
| id   | name    |
+------+---------+
|  100 | zhaoliu |
|  200 | zhaoliu |
|  300 | zhaoliu |
+------+---------+
3 rows in set (0.00 sec)  

当在窗口2中执行插入操作时,会发生阻塞现象,因为此时窗口1没有提交(即没有释放锁),只有当窗口1执行提交操作时,窗口2中的数据更插入成功。

本文通过实验的方式对MySQL中的四种隔离级别进行验证。可以有效加深对这四种隔离级别的理解。

如有错误,请指正。谢谢

原文地址:https://www.cnblogs.com/nongdingan/p/11614241.html

时间: 2024-11-04 17:30:24

MySQL中四种隔离级别的演示的相关文章

MySQL中四种常用存储引擎的介绍

MySQL常用的四种引擎的介绍 (1):MyISAM存储引擎: 不支持事务.也不支持外键,优势是访问速度快,对事务完整性没有 要求或者以select,insert为主的应用基本上可以用这个引擎来创建表 支持3种不同的存储格式,分别是:静态表:动态表:压缩表 静态表:表中的字段都是非变长字段,这样每个记录都是固定长度的,优点存储非常迅速,容易缓存,出现故障容易恢复:缺点是占用的空间通常比动态表多(因为存储时会按照列的宽度定义补足空格)ps:在取数据的时候,默认会把字段后面的空格去掉,如果不注意会把

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

以下内容出自<高性能MySQL>第三版,了解事务的ACID及四种隔离级有助于我们更好的理解事务运作. 下面举一个银行应用是解释事务必要性的一个经典例子.假如一个银行的数据库有两张表:支票表(checking)和储蓄表(savings).现在要从用户Jane的支票账户转移200美元到她的储蓄账户,那么至少需要三个步骤: 1.检查支票账户的余额高于或者等于200美元. 2.从支票账户余额中减去200美元. 3.在储蓄帐户余额中增加200美元. 上述三个步骤的操作必须打包在一个事务中,任何一个步骤失

MySQL有四种BLOB类型

先说明一下Blob的类型,直接从网上摘抄了!!!1.MySQL有四种BLOB类型: ·tinyblob:仅255个字符 ·blob:最大限制到65K字节 ·mediumblob:限制到16M字节 ·longblob:可达4GB2.除了类型对后面存取文件大小有限制,还要修改mysql的配置文件. Windows.linux基本一样通过修改文件my.ini或my.cnf文件,在文件中增加 max_allowed_packet=10M(就是最大10M,mysql默认似乎1MB,增加前先查找一下确保没有

MySQL的四种事务隔离级别

一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样.也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位. 2.一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 .比如A向B转账,不可能A扣了钱,B却没收到. 3.隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不

mysql的四种启动方式

mysql的四种启动方式: 1.mysqld 启动mysql服务器:./mysqld --defaults-file=/etc/my.cnf --user=root 客户端连接: mysql --defaults-file=/etc/my.cnf or mysql -S /tmp/mysql.sock 2.mysqld_safe 启动mysql服务器:./mysqld_safe --defaults-file=/etc/my.cnf --user=root & 客户端连接: mysql --de

android在代码中四种设置控件背景颜色的方法(包括RGB)

转载请注明出处: http://blog.csdn.net/fth826595345/article/details/9208771  TextView tText=(TextView) findViewById(R.id.textv_name); //第1种: tText.setTextColor(android.graphics.Color.RED);//系统自带的颜色类 // 第2种: tText.setTextColor(0xffff00ff);//0xffff00ff是int类型的数据

Linux中四种进程或线程同步互斥控制方法

原文地址:http://blog.itpub.net/10697500/viewspace-612045/ 一.Linux中 四种进程或线程同步互斥的控制方法: 1.临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问. 2.互斥量:为协调共同对一个共享资源的单独访问而设计的. 3.信号量:为控制一个具有有限数量用户资源而设计. 4.事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始. 二.临界区(Critical Section) 保证在某一时刻只有一个线程

jsp中四种范围的使用

///////////////////////////jsp中四种范围中的值的获取////////////////////////////////在pageContext,request,session,application四种范围中设置setAttribute()时:1.pageContext:pageContext.setAttribute(),只能在其本页面中取得值,pageContext.getAttribute() 2.request:request.setAttribute(),在

css样式表中四种属性选择器

css样式表中四种属性选择器1> 简易属性 tag[class]{ font-weight:bold } It will affect all tag with any class. e.g. <h2 class="old" > or <h2 class="new"> 2>精确属性值 a[href="http://www.cnblogs.cn"][title="textTitle"]{fon