美文网首页
MySQL事务的隔离级别

MySQL事务的隔离级别

作者: ggcoder | 来源:发表于2020-06-02 18:53 被阅读0次

    一、事务的基本要素(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事务隔离级别


    image.png

    四、四个隔离级别的具体情况

    • 读未提交(Read Uncommitted)

    读未提交,顾名思义,就是可以读到未提交的内容。
    因此,在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。
    如无特殊情况,基本是不会使用这种隔离级别的。

    • 读提交(Read Committed)

    读提交,顾名思义,就是只能读到已经提交了的内容。
    这是各种系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。这种隔离级别能够有效的避免脏读,但除非在查询中显示的加锁,如:

    select * from T where ID=2 lock in share mode;
    select * from T where ID=2 for update;
    

    不然,普通的查询是不会加锁的。
    那为什么“读提交”同“读未提交”一样,都没有查询加锁,但是却能够避免脏读呢?
    这就要说道另一个机制“快照(snapshot)”,而这种既能保证一致性又不加锁的读也被称为“快照读(Snapshot Read)”
    假设没有“快照读”,那么当一个更新的事务没有提交时,另一个对更新数据进行查询的事务会因为无法查询而被阻塞,这种情况下,并发能力就相当的差。
    而“快照读”就可以完成高并发的查询,不过,“读提交”只能避免“脏读”,并不能避免“不可重复读”和“幻读”。
    mysql默认的事务隔离级别为repeatable-read

    • 可重复读(Repeated Read)

    可重复读,顾名思义,就是专门针对“不可重复读”这种情况而制定的隔离级别,自然,它就可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。
    在这个级别下,普通的查询同样是使用的“快照读”,但是,和“读提交”不同的是,当事务启动时,就不允许进行“修改操作(Update)”了,而“不可重复读”恰恰是因为两次读取之间进行了数据的修改,因此,“可重复读”能够有效的避免“不可重复读”,但却避免不了“幻读”,因为幻读是由于“插入或者删除操作(Insert or Delete)”而产生的。

    • 串行化(Serializable)

    这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。
    这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。

    五、总结
    为什么会出现“脏读”?因为没有“select”操作没有规矩。
    为什么会出现“不可重复读”?因为“update”操作没有规矩。
    为什么会出现“幻读”?因为“insert”和“delete”操作没有规矩。
    “读未提(Read Uncommitted)”能预防啥?啥都预防不了。
    “读提交(Read Committed)”能预防啥?使用“快照读(Snapshot Read)”,避免“脏读”,但是可能出现“不可重复读”和“幻读”。
    “可重复读(Repeated Red)”能预防啥?使用“快照读(Snapshot Read)”,锁住被读取记录,避免出现“脏读”、“不可重复读”,但是可能出现“幻读”。
    “串行化(Serializable)”能预防啥?排排坐,吃果果,有效避免“脏读”、“不可重复读”、“幻读”,不过效果谁用谁知道。

    参考:
    https://www.cnblogs.com/index01/p/12101744.html
    https://baijiahao.baidu.com/s?id=1611918898724887602&wfr=spider&for=pc
    https://www.cnblogs.com/wyaokai/p/10921323.html

    相关文章

      网友评论

          本文标题:MySQL事务的隔离级别

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