GVKun编程网logo

MySQL四种隔离级别和MVCC(mysql四种隔离级别的区别)

17

在本文中,我们将带你了解MySQL四种隔离级别和MVCC在这篇文章中,我们将为您详细介绍MySQL四种隔离级别和MVCC的方方面面,并解答mysql四种隔离级别的区别常见的疑惑,同时我们还将给您一些技

在本文中,我们将带你了解MySQL四种隔离级别和MVCC在这篇文章中,我们将为您详细介绍MySQL四种隔离级别和MVCC的方方面面,并解答mysql四种隔离级别的区别常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的30秒读懂mysql四种事务隔离级别、MySQL MVCC && 事务隔离级别 && 锁、Mysql 事务的四种隔离级别、mysql 事宜的四种隔离级别

本文目录一览:

MySQL四种隔离级别和MVCC(mysql四种隔离级别的区别)

MySQL四种隔离级别和MVCC(mysql四种隔离级别的区别)

事务在一个数据库中的地位尤为重要,尤其是高并发的场合。保证数据库操作的原子性和错误出现情况下的回滚,对数据的安全性和可靠性提供了保障。事务有四大原则,即ACID原则。网上关于这个问题的文章有很多,读者可以到网上看看相关的文章,我这里就不赘述了。但是需要注意的是,MysqL默认是不开启事务的,默认情况是autocommit自动提交,而如果想开启事务,需要数据库管理员或者开发者手动输入begin来开启事务。

本文主要介绍四大原则中的I原则,即隔离级别。并在讲述I原则的时候,顺带讨论MVCC。因为MVCC通常和隔离级别是讨论到一块的。

事务的隔离级别其实是sql语言的标准,这里我就以自己比较常用的MysqL数据库为例进行介绍。

客户端输入命令:

SET [SESSION | GLOBAL]  TRANSACTION  ISOLATION  LEVEL

 {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

小提示:也可以使用小写,MysqL是不分大小写的。

在MysqL Workbench输入命令查询系统默认的隔离状态

MysqL默认情况下是repeatable read。

设置当前会话隔离级别

设置当前会话(客户端)的隔离级别,当客户端关闭后重新进入,隔离级别会恢复到系统的全局隔离状态。

理解‘当前会话’:

MysqL中认为,打开一个客户端就是开启一个会话。其实质是建立一个网络连接。这个网络连接是有状态性的,一旦关闭,此会话级别中设置的变量就会恢复为系统的变量。

 

设置全局隔离级别

设置全局隔离级别的时候,只对全局进行修改,当前会话还是会保持原来的设置,退出重新登录才会遵循全局的设置。

在MysqL Workbench中输入命令:

bed541a6636a20009677745286e1d.png" alt="">

 

MysqL> show variables like +-----------------------+----------------+ | Variable_name | Value | +-----------------------+----------------+ | transaction_isolation | READ-COMMITTED | | tx_isolation | READ-COMMITTED | +---------------- ------+----------------+ 2 rows set,1 warning (0.00 sec)

另外一种方法:

在ini文件(Linux为conf文件)设置全局的隔离级别

[MysqLd]

添加:

transaction-isolation = READ-COMMITTED

不过这种情况需要重启服务器,所以不太建议使用这种方式,除非是几乎没有请求的深夜时候进行。

C:\WINDOWS\system32>MysqL

MysqL 服务正在停止..

MysqL 服务已成功停止。

C:\WINDOWS\system32><span> net start MysqL

MysqL 服务正在启动 .

MysqL 服务已经启动成功。

 关于以上命令,有一些需要理解的点:

1)隔离级别优先级顺序 read  uncommittd < read  committed < repeatable  read < serializable

我的理解是每一个级别都是在上一级别的基础上增加了表操作的限制。读者往下看就可以体会到这种限制的加强。

2)session和global

1. 默认行为(不带session和global)是为下一个(未连接)会话设置隔离级别。

2. 如果使用GLOBAL关键字,此命令语句在全局中对从那点开始创建的所有新连接设置事务级别。

3. 使用SESSION 关键字为当前连接上执行的事务设置默认事务级别。

4. 任何客户端在任何时候都能自由改变会话/全局隔离级别(甚至在事务的中间),或者为下一个事务设置隔离级别。

实际测试中,由于是本地连接,一些情况无法模拟出来,而且手动也很难做一些模拟高并发的情形,可以借助一些测试工具来进行。例如sysbench,《高性能MysqL》中也有一章专门写了基准测试。

下面是对四个隔离级别的介绍

1. Read Uncommitted   读取未提交的事务

一个数据库连接实例中,它的未提交事务执行了对数据库的增删改操作,这些操作对数据的更改是没有提交到服务器磁盘的,但是在高并发的情况下,本连接的事务会不断更新数据库以获取其他连接的事务对数据库进行的最新的更改。那么第一个事务查询操作读取的数据可能是不真实的,人家都还没有提交!所以这种情况下就会出现了所谓的脏读。一般,在现实中很少使用这个级别,除非是对数据的真实性要求不高,只想获得最新的数据的情况。想想在一些金融领域的电子现金系统或者商城购物车系统使用这个级别会是怎样一个情形?

2. Read Committed    读取已经提交的事务

      此级别在本会话中对数据库进行查询,会读取已经提交(commit)了sql语句的事务结果,而未提交的事务的操作对数据库所造成的影响是不会读取的。可以这样理解,这个级别更像是‘事务级别’,即不同事务间内部的操作互不影响,只有提交了事务才会对其他事务产生影响。

Read  committed级别同时也是nonrepeatable read级别(是相对下面的Repeatable  Read而言的),即不要求重复读。一个事务前后两次的读取内容可以是不同的,即允许在本事务查询的过程中其他事务对本事务查询的数据进行其他操作,这样就会出现前后两次读取的数据的不一致性。此处涉及到MVCC和乐观锁、悲观锁的概念,后面会讲述。我们先讨论这种机制的运行逻辑。

   想象一下下面这种情形:高并发情况下,多个数据库连接同时对数据库提交操作。本事务由于sql语句比较多,执行起来比较慢。而在这期间(有时可能是1s内),有另外两个连接同时在执行操作,一个连接对一行数据的某一列进行增加2操作,而另外一个连接对同一行数据的这一列数据进行减3操作,它们在对数据库的实现上可能相差的时间很小,可能仅在毫秒之间这个时候就会出现两个vesion版本的结果,一个是执行了一个事务的版本,另一个是执行了两个事务的版本。那么本事务究竟读取哪一个版本呢?答案是指读取执行了两条事务的版本。因为在本事务内,会不断去‘查看’其他事务的提交情况,并将最新的提交情况‘反馈’在本事务中。

3. Repeatable  Read   可重复读

      Repeatable  Read正好与上面的Read  Committed相反,本事务会读取第一个version的数据。因为在进行第一次查询操作的时候,可能第一个事务已经提交了,而第二个事务还没提交。而无论后面第二个事务甚至更多个事务提交了,但本事务中再次读取的数据时只会读取是第一读取的相同数据,即‘无视’其他事务对此行数据的更改。可以理解,在这里是悲观锁发挥了作用,即锁住了本事务,其他事务的数据的更改就无法影响到本事务。而在Read  Committed级别中,发挥作用的是乐观锁,其实就是什么也不锁定,只在更新数据的时候锁定(下面有更详细描述)。所以在本事务的前后两次范围查询中会出现数据不一致的幻读现象。

4. Serilizable 串行化

       数据库最高级别的隔离限制,事务与事务之间串行化的。即一个事务在执行任何操作的时候,都不允许其他事务对本事务查询范围内的数据有任何操作,这里会引入一个共享锁的概念,即本事务的查询操作别读取的数据锁住了,必须等本事务完成之后才允许其他事务获取这个共享锁进行其他操作,就好比如排着队一个个执行。

MVCC

MVCC,Multiversion Concurrency Control多版本并发控制。MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此服务器的开销更低(减少了锁的生产和分配)。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。

在实现上,MysqL通过三个列实现对版本的控制,即6字节的事务ID(DB_TRX_ID)字段,7字节的回滚指针(DB_ROLL_PTR)字段 ,6字节的DB_ROW_ID字段。更多相关内容推荐看这篇文章,里面讲得很详细 https://juejin.im/entry/5a4b52eef265da431120954b

而实际上InnoDB并非完全意义上的MVCC,因为没有实现多版本并存。关键在于并存两字,即在事务执行对数据操作时同时存在多个版本。而无论如何MysqL在事务执行的时候是串行化的,即使这两个事务几乎同时发生。其实这正是对数据安全性的一个保障。

MVCC只在 READ  COMMITTED 和 REPEATABLE  READ 两个隔离级别下工作。其他两个隔离级别和MVCC不兼容。

悲观锁:

悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。

乐观锁:

乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完事务操作需要实际更新数据的最后一步再去拿一下锁就好。

在实战中怎么使用,还是要看具体的数据量和业务逻辑来进行选择。

更新说明:随着自己对MysqL数据库隔离级别的更多理解,本文在之前的内容基础上进行重新整理,并且添加上了MVCC的内容。18.12.25

参考文章:

https://www.cnblogs.com/PHPper/p/7345332.html

https://juejin.im/entry/5a4b52eef265da431120954b

30秒读懂mysql四种事务隔离级别

30秒读懂mysql四种事务隔离级别

一、事务的基本要素(ACID)

  1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

   2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

   3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

   4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

 

二、事务的并发问题

  1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

  2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

  3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

  小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

 

三、MySQL事务隔离级别

事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommitted) 是 是 是 不可重复读(read-committed) 否 是 是 可重复读(repeatable-read) 否 否 是 串行化(serializable) 否 否 否

mysql默认的事务隔离级别为repeatable-read

未提交读

未提交读的意思就是比如原先name的值是小刚,然后有一个事务B`update table set name = ''小明'' where id = 1`,它还没提交事务。同时事务A也起了,有一个select语句`select name from table where id = 1`,在这个隔离级别下获取到的name的值是小明而不是小刚。那万一事务B回滚了,实际数据库中的名字还是小刚,事务A却返回了一个小明,这就称之为脏读。

未提交读

 

 

已提交读

按照上面那个例子,在已提交读的情况下,事务A的select name 的结果是小刚,而不是小明,因为在这个隔离级别下,一个事务只能读到另一个事务修改的已经提交了事务的数据。但是有个现象,还是拿上面的例子说。如果事务B 在这时候隐式提交了时候,然后事务A的select name结果就是小明了,这都没问题,但是事务A还没结束,这时候事务B又`update table set name = ''小红'' where id = 1`并且隐式提交了。然后事务A又执行了一次`select name from table where id = 1`结果就返回了小红。这种现象叫不可重复读。

 

 

已提交读

可重复读

可重复读就是一个事务只能读到另一个事务修改的已提交了事务的数据,但是第一次读取的数据,即使别的事务修改的这个值,这个事务再读取这条数据的时候还是和第一次获取的一样,不会随着别的事务的修改而改变。这和已提交读的区别就在于,它重复读取的值是不变的。所以取了个贴切的名字叫可重复读。按照这个隔离级别下那上面的例子就是:

可重复读

 

 

串行化

上面三个隔离级别对同一条记录的读和写都可以并发进行,但是串行化格式下就只能进行读-读并发。只要有一个事务操作一条记录的写,那么其他要访问这条记录的事务都得等着。

串行化

 

 

一般没人用串行化,性能比较低,常用的是已提交读和可重复读。而已提交读和可重复读的实现主要是基本版本链和readView。而它们之间的区别其实就是生成readView的策略不同

 

MySQL MVCC && 事务隔离级别 && 锁

MySQL MVCC && 事务隔离级别 && 锁

MySQL MVCC && 事务隔离级别 && 锁

InnoDB多版本并发控制——MVCC

http://my.oschina.net/xinxingegeya/blog/208821

MySQL_S锁_X锁_read lock_write lock

http://my.oschina.net/xinxingegeya/blog/215417

MySQL事务隔离级别

http://my.oschina.net/xinxingegeya/blog/215419

MySQL命令行控制事务

http://my.oschina.net/xinxingegeya/blog/296459

MySQL REPEATABLE-READ && 幻读

http://my.oschina.net/xinxingegeya/blog/296513

MySQL/InnoDB锁机制

http://my.oschina.net/xinxingegeya/blog/296591

MySQL事务隔离级别之REPEATABLE-READ

http://my.oschina.net/xinxingegeya/blog/296612

MySQL锁表_LOCK TABLES_UNLOCK TABLES

http://my.oschina.net/xinxingegeya/blog/341593

MySQL Concurrency Problems

http://my.oschina.net/xinxingegeya/blog/351347

MySQL锁的调试

http://my.oschina.net/xinxingegeya/blog/351559

MySQL事务隔离级别和锁

http://my.oschina.net/xinxingegeya/blog/499717

事务隔离级别-REPEATABLE-READ && 间隙锁

http://my.oschina.net/xinxingegeya/blog/499867

InnoDB存储引擎MVCC的工作原理

http://my.oschina.net/xinxingegeya/blog/505675

==========END==========

Mysql 事务的四种隔离级别

Mysql 事务的四种隔离级别

开发工作中我们会使用到事务,那你们知道事务又分哪几种吗?
MYSQL标准定义了4类隔离级别,用来限定事务内外的哪些改变是可见的,哪些是不可见的。
低的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
隔离级别由低到高:Read Uncommitted Read Uncommitted(读取未提交内容)

在该隔离级别,所有事务都可以看到其他未提交(commit)事务的执行结果。
本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。
读取未提交的数据,也被称之为脏读(Dirty Read)。[窗口A]:

mysql> set GLOBAL tx_isolation=''READ-UNCOMMITTED'';
Query OK, 0 rows affected (0.00 sec)

mysql> quit;
Bye

[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登录)

mysql> SELECT @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

mysql> use test;
Database changed
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)

[窗口B]:
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test.user values (3, ''c'');
Query OK, 1 row affected (0.00 sec)

mysql> select * from user;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
+----+------+
3 rows in set (0.00 sec)

//目前为止,窗口B并未commit;

[窗口A]:
mysql> select * from user ;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
+----+------+
3 rows in set (0.00 sec)Read Committed(读取提交内容)

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。
它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。
这种隔离级别 也支持所谓的不可重复读(NonrepeatableRead),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一 select 可能返回不同结果。[窗口A]:

mysql> SET GLOBAL tx_isolation=''READ-COMMITTED'';
Query OK, 0 rows affected (0.00 sec)

mysql> quit;
Bye

[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登录)

mysql> SELECT @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)


[窗口B]:

mysql> SELECT @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)

mysql> delete from test.user where id=1;
Query OK, 1 row affected (0.00 sec)

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  2 | b    |
+----+------+
1 row in set (0.00 sec)

[窗口A]:

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)

[窗口B]:

mysql> commit;
Query OK, 0 rows affected (0.02 sec)

[窗口A]:

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  2 | b    |
+----+------+
1 row in set (0.00 sec)Repeatable Read(可重读)

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。
不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。
简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。
InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。[窗口A]:

mysql> SET GLOBAL tx_isolation=''REPEATABLE-READ'';
Query OK, 0 rows affected (0.00 sec)

mysql> quit;
Bye

[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登录)

mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

[窗口B]:

mysql> quit;
Bye

[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登录)

mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql> insert into test.user values (4, ''d'');
Query OK, 1 row affected (0.00 sec)

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  2 | b    |
|  4 | d    |
+----+------+
2 rows in set (0.00 sec)

[窗口A]:

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  2 | b    |
+----+------+
1 rows in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  2 | b    |
|  4 | d    |
+----+------+
2 rows in set (0.00 sec)Serializable(序列化执行)

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。
简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。 [窗口A]:

mysql> SET GLOBAL tx_isolation=''SERIALIZABLE'';
Query OK, 0 rows affected (0.00 sec)

mysql> quit;
Bye

[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登录)

mysql> SELECT @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE   |
+----------------+
1 row in set (0.00 sec)

mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  2 | b    |
|  4 | d    |
+----+------+
2 rows in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test.user values (5, ''e'');
Query OK, 1 row affected (0.00 sec)

[窗口B]:

mysql> quit;
Bye

[root@vagrant-centos65 ~]# mysql -uroot -pxxxx(重新登录)

mysql> SELECT @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE   |
+----------------+
1 row in set (0.00 sec)

mysql> select * from test.user;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

[窗口A]:

mysql> commit;
Query OK, 0 rows affected (0.01 sec)

[窗口B]:

mysql> mysql> select * from test.user;
+----+------+
| id | name |
+----+------+
|  2 | b    |
|  4 | d    |
|  5 | e    |
+----+------+
3 rows in set (0.00 sec)Thank ~

来源:http://mp.weixin.qq.com/s?__biz=MjM5NDM4MDIwNw==&mid=2448834642&idx=1&sn=c02c5cc8ab0c1f29142ac8f8aa6b78af#rd

更多【干货分享】,请关注我的个人订阅号。
Mysql 事务的四种隔离级别

mysql 事宜的四种隔离级别

mysql 事宜的四种隔离级别

mysql 事务的四种隔离级别 !--[if !mso] style v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} /style ![endif]-- ? 我们知道事务有四种特性 ? ( 1 )原

mysql 事务的四种隔离级别

?

我们知道事务有四种特性

?

1)原子性:一个事务被视为不可分割的一个单位

?

2)隔离性:事务之间隔离开来,一个事务所做的修改,未提交之前另一个事务是不可见的

?

3)永久性:事务的更改是永久的

?

4)一致性:数据库总是从一个一致性的状态转换到另外一个一致性的状态中

?

?

?

在此之前,我们来学习一下mysql 如何设置隔离级别

?

SELECT@@global.tx_isolation;

?

SELECT@@session.tx_isolation;

?

SELECT@@tx_isolation;

?

set tx_isolation = ''read-uncommited'';设置默认隔离级别

?

1、默认:下一个事务开始

?

2session:当前链接

?

3global:从此开始,全局都是

?

隔离级别:

?

1Read Uncommited(读未提交):发生脏读

?

?客户端A

?

开始状态:

?




?
?

?

客户端B

?

?

2、客户端A开始事务,但是没有提交,客户端B可以看到

?

1)、客户端A的状态:

?




?
?

?

?

?

客户端B的状态:

?

?

?




?
?

?

?

?

2)开始事务,并在客户端改变值

?




?
?

?

?

?

3)这时候查看客户端B,可以看到变化,这就是脏读现象

?




?
?

?

?

?

2Read Committed (读提交):容易发生“不可重复读”

?

1、首先先改变两边的状态

?

客户端A

?

?

?

?

?




?
?

?

?

?

客户端B

?




?
?

?

2、客户端A开始事务,客户端B也开始事务

?

?

?




?
?

?

3、这时候A更新一条记录,并且提交完毕,B未提交事务,又读了一次,这时候,两次读的数据不一致,导致了不可重复读

?

?

?

客户端A

?

?

?




?
?

?

?

?

客户端B

?





?
?
?

?

?

?

简单的来说

?

客户端A

客户端B

事务开始

事务开始

?

读字段namelin

更新字段name=qin

?

提交事务

?

?

读字段nameqin,两次读都不一致

?

提交事务

?

?

?

?

?

3Repeatable Read(可重复读):幻读现象

?

简单的用表格表示下:

?

客户端A

客户端B

事务开始

事务开始

name=lin

?

?

更新name=qin

?

Commit提交事务

name还是为lin

事务2开始

?

插入一条数据

?

?

?

?

?

?

?

1、???????? 改变事务隔离级别

?





?
?
?

?

2、???? 客户端B改变并且提交

?





?
?
?

?

?

?

3、???? 客户端A两次读都未发生不可重复读现象

?

?

?

?

?




?
?

?

?

?

4、???????? 客户端B插入一条记录(还未提交)

?




?
?

?

?

?

5、???????? 查看客户端A未发生变化,这时候客户端B提交

?




?
?

?

?

?

6、???????? 再次查看客户端A的数据,还是没有发生任何问题

?

?

?



?

?

?

?

所以mysql到了repeatable read级别之后,没有出现任何问题

?

这是因为innoDB存储引擎通过MVCC(多版本控制)解决了幻读的问题。

?

关于MySQL四种隔离级别和MVCCmysql四种隔离级别的区别的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于30秒读懂mysql四种事务隔离级别、MySQL MVCC && 事务隔离级别 && 锁、Mysql 事务的四种隔离级别、mysql 事宜的四种隔离级别的相关信息,请在本站寻找。

本文标签:

上一篇MySQL聚簇索引(mysql聚簇索引和非聚簇索引区别)

下一篇mysql No query specified