MySQL的四种事务隔离级别

mysql事物隔离级别分为四种:

  • READ-UNCOMMITTED            0 --> 读未提交
  • READ-COMMITTED                 1 --> 读已提交
  • REPEATABLE-READ                2 --> 可重复读
  • SERIALIZABLE                         3 --> 序列化

mysql中查看事务的隔离级别用的是tx_isolation,5.7.20版本之后,用的是transaction_isolation

查看隔离级别命令:

SHOW [GLOBAL] VARIABLES LIKE 'tx_isolation';  #mysql5.7版本以前的使用方法

SHOW [GLOBAL] VARIABLES LIKE 'transaction_isolation';  #mysql5.7版本后的使用方法

或者

select @@tx_isolation; 

select @@transaction_isolation; 

设置隔离级别的方法是:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

或

SET [SESSION|GLOBAL] tx_isolation=[0|1|2|3];              #mysql5.7以前

SET [SESSION|GLOBAL] transaction_isolation=[0|1|2|3];     #mysql5.7以后

默认mysql的隔离级别为 REPEATABLE-READ(可重复读),查看方法如下:

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

show global variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)

READ-UNCOMMITTED 


该事物隔离级别可读取其它事物未提交的结果

出现的问题:脏读,不可重复读

1、通过mysql -u username -p password 开启两个mysql连接, 分别为A连接, B连接
2、输入set tx_isolation = 'read-uncommitted';或者set tx_isolation=0;将A连接的事务隔离级别设置为READ-UNCOMMITTED
3、在A,B连接的窗口分别查询test1表的数据, 表数据一致, 如下图所示

连接A和连接B的数据结果一致

4、在B连接的命令窗口输入start transaction;,并更新相应记录, 但不提交,如下图所示 

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

mysql> update user set user_name='test1' where id=4;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

5、在A连接的命令窗口查看test1表, 结果如下图所示 

通过结果发现。B连接,开启事物,修改数据,并未提交,A连接在read-uncommitted的隔离模式下仍然可以看到已更新的数据。

6、B连接窗口输入rollback回滚数据,此时A,B连接所查询的数据,和初始时的数据是一样的。 

A连接可以读取到B连接已提交的数据 

READ-COMMITTED


该事物隔离级别只会读取已提交的数据,在事务中已更改但未读取的数据不会读取

解决的问题:可以解决脏读问题

产生的问题:不可重复读

1、同上A,B 两个连接

2、输入set tx_isolation = 'read-committed';

3、将A连接的事务隔离级别修改B连接窗口开启事务,更新数据,但不提交,如图

如结果所示,B未提交的数据,A读取不到 

4、此时B提交事物, A继续查询,结果 与上一步不一致,即产生了不可重复读的问题 ,如下图所示

A连接可以读取到B连接已提交的数据 

REPEATABLE-READ


该事务隔离级别只会读取已提交的结果,与READ-COMMITTED不同的是,repeatable-read在开启事务的情况下,同一条件的查询返回的结果永远是一致的,无论其它事物是否提交了新的数据

解决的问题:不可重复读

产生的问题:幻读

幻读在可重复读的模式下才会出现,其他隔离级别中不会出现

1、和READ-COMMITTED的实验环境差不多,此时将A的隔离级别改为 repeatable-read,查询结果如下:

2、B还是一样开启事物,更新数据, 此事暂时不提交。但A开启事物查询数据。

如结果所示,B未提交的数据,A读取不到 

2、此时B提交事物, A继续查询会查询到B更改的结果如下图所示

由上图可以看出,A连接端在B连接端提交事务前和后,查询的数据结果并没有改变

SERIALIZABLE 


这种隔离级别和repeatable-read类似,只会读取其它事物已提交的内容,有一点不同的地方在于,如果autocommit为false,那么每一条select语句会自动被转化为select ... lock in share mode.这样出现一些阻塞情况

解决的问题:脏读、不可重复读,幻读

1、设置事务级别为序列化

2、B开启事务, 并更新数据,但不提交 

3、A 隔离级别改为serializable, 并且开启事务或者将autocommit设置为0, 并查询被修改数据,如图

如果此时A连接端也开启事务修改数据

B连接端查询时会出现阻塞

从上图可以看出

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

         这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:

         脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

         不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

         幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

         在MySQL中,实现了这四种隔离级别,分别有可能产生问题如下所示:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值