您的位置:首页 > 数据库 > MySQL

彻底搞懂mysql隔离级别和事务

2019-04-03 11:11 337 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_37779793/article/details/88978215

前言

       我们都知道,mysql的InnoDB存储引擎支持事务操作,事务ACID特性中的隔离性可以使当前事务中的操作不受其他事务操作的影响,然而,这个隔离性是和隔离级别相关的特性,不同的隔离级别对隔离的严格性不同,对不同的隔离级别一一实验后,我们会发现,如果单单说事务的隔离性不受其他事务的影响,这句话是不太准确的,或者说是不严谨的说法。作为一个工科,我觉得能看到一个示例,比单纯看理论更能让人理解、记忆深刻。

一、查看和设置当前的隔离级别:      

我们先登录mysql终端,查看和设置当前的隔离级别:

mysql> show variables like '%isolation%';

+---------------+-----------------+

| Variable_name | Value           |

+---------------+-----------------+

| tx_isolation  | REPEATABLE-READ |          //mysql默认的是RR的隔离级别

+---------------+-----------------+

1 row in set (0.00 sec)

 

或者执行以下命令:

mysql> select @@global.tx_isolation, @@tx_isolation;

+-----------------------+-----------------+

| @@global.tx_isolation | @@tx_isolation  |

+-----------------------+-----------------+

| REPEATABLE-READ       | REPEATABLE-READ |

+-----------------------+-----------------+

1 row in set (0.00 sec)

 

 

// 修改事务隔离级别:

可以  help ISOLATION 查看一下都有哪些隔离级别,或者直接

set session transaction isolation level 事务隔离级别,如设置成RU隔离级别:

set session transaction isolation level READ UNCOMMITTED;

 

二、两个事务的比较

    注意: 事务回退之后,自增id也会隐形加1 ,例如回退的那行的id是3,那么下次再添加的时候,id就会变成4了

    (1)隔离级别是RU(未提交读)

     未提交读: 是指开启的两个事务,如果一个事务修改了内容,那么即使没有提交,在另一个事务中也能看到改动  。

        a)insert: 事务不会阻塞,各个事务进行各自的插入,插入的数据不管提不提交 ,都能被另一个事务看到,所以也叫未提交读

        比如开启一个事务A 和 事务B:

     

 

        b)update:    更新同一行数据,事务会阻塞,超时,被阻塞的事务会退出事务;但是更新不是同一行,那么和insert情形一致。

(i)更新同一行的情形

   (j)更新不是同一行的情形

     select:  有影响,因为未提交读,所以同样的查询条件  的结果可能都不一样。

              这里也会出现脏读、幻读和不可重复读。

            (个人以为,其实脏读、幻读、不可重复读没有什么明显的界限区别,都是同样的查询导致不同的结果,你可以说这是脏读、也可以说是幻读,还可以说是不可重复读!只不过是由于查询的范围不同,导致不同的名称,如下:

              脏读: 一般是查询一条或几条特定的数据,由于其他事务的干扰,不管是否提交,我们再次查询时,会查询到被修改(被污染)的数据。

              幻读:  一般是查询范围时,由于其他事务的干扰,不管是否提交,我们再次查询这个范围时,可能会多查出或少查出几条数据,就好像发生了幻觉一样

              可重复和不可重复读:  这个主要是指 多个事务当中,其中一个事务做了修改且已提交,那么在其他的事务当中,查询被修改的这条记录,如果每次查询的都是已修改后的数据,说明同样的查询得到不同的查询结果,查询结果是不重复的,所以也叫不可重复读;  可重复读相反,每次查询的结果都是修改前的结果,所以也叫可重复读! 一般来说,可重复和不可重复,主要是针对RC和RR的隔离级别的。

                个人观点,大佬勿喷!)

              

      delete:  删除同一行数据,事务会阻塞,超时,被阻塞的sql失效; 如果删除不是同一行数据,那么和insert情形一致

       (i)删除同一行

      (j)删除不是同一行

    (2)隔离级别是RC (提交读 或不可重复读)

        两个事务虽然有共同的操作,但在都没有提交之前互不影响,自己进行自己的查询更新等操作,但是一旦有个事务提交,那么另一个事务就会收到影响。

        insert: 事务不会阻塞,事务在提交之前,另一个事务是不会看到改动的,但是第一个事务一旦提交,另一个事务不管提不提交都会看到改动

       

 

        update: 更新同一行数据,事务会阻塞,超时,被阻塞的事务会退出事务;如果更新不是同一行数据,那么和insert的情形一致。

        select: 在两个事务提交之前,查询的都是事务开启之前的数据,一旦有一个事务提交,那么不管另一个事务是否提交,查询的都是最新的那个事务的提交结果, 也即是不可重复读

      

 delete:  删除同一行数据,事务会阻塞,超时,被阻塞的sql失效;如果删除的不是同一行,那么和insert情形一致。

 

    (3)隔离级别是RR (可重复读)

        insert: 事务不会阻塞,事务在提交之前,另一个事务是不会看到改动的,即使是第一个事务提交,另一个事务如果不提交,那么也看不到第一个事务提交的结果,在本事务中,每次查询都是返回同样的结果,所以也叫 可重复读。

       

 

        update: 更新同一行数据,事务会阻塞,超时,被阻塞的sql失效;如果不是更新同一行,那么和insert情形一致。

        select: 事务的修改互不影响, 可重复读,这个隔离级别也解决了幻读(通过MVCC机制取快照读的方式)的问题。

        

delete:  删除同一行数据,事务会阻塞,超时,被阻塞的sql会失效;如果删除的不是同一行,那么的insert的情形一致。

 

    (4)隔离级别是 serializable (可串行化)   --  这个隔离级别相当于 表锁

        insert: 事务不会阻塞,可以正常在事务内insert,  但是select的时候会阻塞,另一个事务如果也select,会造成死锁回滚

        update: 更新即使不是同一行,也会相互阻塞

        select:  两个事务查询会相互阻塞

        delete:   删除不是同一行数据,也会相互阻塞

        这个隔离级别是最严格的隔离级别,所以我们可以得出一个结论:

        serializable的隔离级别下:  一个事务开启的时候,另一个事务除了insert以外,   select、update、delete操作都会阻塞

 

 

 

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: