• 记一次Mysql事务隔离级别的坑


    最近在写代码调试时,遇到了一个问题。

    遇到问题

    具体操作如下:
    1.调用方法A,并且方法A加上了@Transactional事务注解。
    2.在方法A内部,查询并更新某个字段F的值。
    3.处理其他逻辑。
    4.查询并打印日志,记录关键字段的值,包括字段F。
    5.方法A结束。
    由于刚刚接手这块代码,而且这个方法又写得很长,所以很多逻辑都没法细看,只能慢慢调试。
    我在第4步打了断点,调试时查看日志,感觉数据有问题,将sql复制到数据库里面手动跑了一遍,
    发现在方法里和数据库里,执行同一条Sql,结果竟然不一样。
    一开始还有点蒙圈,以为是IDE的bug,可能是缓存之类的问题。
    然后又调试了几遍,单步调试时观察到手动在数据库里查出来的字段值,总是方法刚开始还未变更时的值
    恍然才明白,原来是事务隔离级别造成的。

    事务隔离级别

    这些知识点,其实以前面试都背得滚瓜烂熟。现在时间久了,一下子又忘光了。
    Q:数据库的隔离级别有哪些?
    读未提交(read-uncommitted)读提交(read-committed) 可重复读(repeatable-read)串行化(serializable)。
    Q:mysql默认的数据库隔离级别是什么?
    可重复读(repeatable-read)

    一致性非锁定读

    Mysql采用INNODB存储引擎。SELECT操作,使用一致性非锁定读。
    在READ COMMITTED事务隔离级别下,对于快照数据,非一致性读总是读取被锁定的行的最新一份快照数据。
    在REPEATABLE READ(可重复读)事务隔离级别下,对于快照数据,非一致性读总是读取事务开始时的行数据版本。
    而我遇到的问题,就是说事务A开启后,变更了数据,还没有提交,然后事务B就去进行查询。
    因为默认的REPEATABLE READ事务隔离级别,读取到的是事务开始时的行数据版本。

    不同事务隔离级别可能出现的问题

    1.脏读
    脏读:脏数据是指未提交的数据。脏读是指在不同的事务下,当前事务可以读到另外事务未提交的数据。这显然违反了数据库的隔离性。
    脏读发生的事务隔离级别:READ UNCOMMITED。
    2.不可重复读
    不可重复读:在一个事务内两次读到的数据不一样。比如,A事务还没有结束,B事务对同一数据进行修改,由于B事务的修改,那么A事务两次读到的数据是不一样的。违背了数据库事务一致性的要求。
    不可重复读,读到的是已经提交的数据。
    不可重复读,发生的隔离级别是READ COMMITTED。
    3.幻读:A事务读取了B事务已经提交的新增数据。
    4.丢失更新
    丢失更新,是指一个事务的更新操作会被另一个事务的更新操作覆盖。

    参考资料:《Mysql技术内幕》

  • 相关阅读:
    习题2-7
    习题2-6
    习题2-5
    习题2-4
    习题2-3
    作业二 分支循环结构
    2- 8
    实验三-计算圆柱体积
    实验三-计算n个圆柱体体积
    实验3-计算圆面积
  • 原文地址:https://www.cnblogs.com/expiator/p/11610642.html
Copyright © 2020-2023  润新知