美文网首页
事务隔离级别测试

事务隔离级别测试

作者: c108cb39fd41 | 来源:发表于2019-02-09 20:15 被阅读0次

    MYSQL事务的四种隔离级别简介

    读未提交

    其他事务未提交的数据变更对本事务可见。

    读已提交

    其他事务未提交的数据变更对本事务不可见。

    可重复读

    在一次事务里,本事务对某行记录多次读取的结果是一致的,即使中间有其他事务提交了对该数据的变更。

    序列化

    多个事务之间必须串行执行,事务之间的操作不可交叉。

    ——————————————————————

    |  隔离级别  |     脏读     |   不可重复读   |    幻读    |

    ——————————————————————

    |读未提交    |       Y        |           Y           |      Y      |   

    ——————————————————————

    |读已提交    |      X        |            Y           |        Y    |

    ——————————————————————

    |可重复读    |      X        |            X            |        Y   |

    ——————————————————————

    |序列化       |      X        |            X            |        X    |

    测试

    测试数据准备

    CREATE TABLE `People` (

      `ID` bigint(20) NOT NULL,

      `Name` varchar(255) NOT NULL,

      `Age` int(11) NOT NULL

    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    INSERT INTO `People` (`ID`, `Name`, `Age`)

    VALUES (1, '炒饭', 31),(2, '阿丹', 33)

    脏读

    事务1    set session transaction isolation level read uncommitted

    事务1    start transaction

    事务2    start transaction

    事务2    update People set Age=32 where ID=1;

    事务1   select * from People where ID=1; 结果

    事务1读到了事务2未提交的数据变更

    解决脏读需要事务1设置隔离级别为读提交read committed

    set session transaction isolation level read committed

    不可重复读

    事务1    set session transaction isolation level read committed

    事务1    start transaction

    事务2    start transaction

    事务1    select * from People where ID=1; 结果

    事务2     update People set Age=33 where ID=1;

    事务2     commit;

    事务1     select * from People where ID=1; 结果

    事务1第一次查询ID=1的记录跟第二次查询结果不一样,称为不可重复读

    解决不可重复读需要设置隔离级别为可重复读

    set session transaction isolation level read repeatable read

    幻读

    幻读,并不是说两次读取获取的结果集不同(可重复读级别已经解决该问题),幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。(很多人对幻读有误解,个人认同这个作者的观点 https://segmentfault.com/a/1190000016566788)

    事务1    set session transaction isolation level repeatable read

    事务1    start transaction

    事务2   start transaction

    事务1    select * from People where ID=1

    事务2   insert into People (ID,Name,Age) values(1,'西西',15)

    事务1    如果select记录不存在,执行insert into People (ID,Name,Age) values(1,'西西',15)

    事务2   commit;

    事务1   commit;

    事务1希望ID=1的记录不存在时去执行插入操作,然而事务2先插入了记录,事务1又插入了一次记录,仿佛之前事务1的select看到的跟幻觉一样。

    在可重复读隔离级别下,避免幻读,可以用select * from People where ID=1 for update,加上行锁,能保证当前事务不受其他事务的写入干扰。

    相关文章

      网友评论

          本文标题:事务隔离级别测试

          本文链接:https://www.haomeiwen.com/subject/wvdzsqtx.html