• mysql的隔离性和锁


    INNODB的隔离性质

    INNODB的事务支持4种隔离机制,分别是 READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READ, and SERIALIZABLE. 其中默认的为REPEATABLE READ.

    下面详细分析这4种隔离性的联系和区别。

    REPEATABLE READ

    在不用锁的查询语句中,此隔离级别保证了每次事务读取到的数据是一致的。

    在用锁的查询中(update等),如果查询是指定索引查询,那么只会在锁住索引中的某个值,如果是指定索引的范围查询,那么会在范围的间隙加锁,也就是间隙锁。

    此隔离级别会有重复读取的问题。

    当你在一个事务中查询两次,可能返回的结果不一样,这是由于在第一次查询结束后,此隔离级别只会锁住对应的值和值的间隙,另一个事务对表进行了插入了原来不存在的值(也就是没有被锁住的值),那么就会导致两次查询的结果不一致。

    // 重复读问题的解释

    https://dev.mysql.com/doc/refman/8.0/en/innodb-consistent-read.html

    READ COMMITTED

    比REPEATABLE READ弱一级,在指定索引查询时,如果是范围查询那么不会加间隙锁,只会锁住某个值,这就会导致幻读的问题。

    举例而言:

    当你有一个索引列,数据为1,3,5,当你查询这一列>1的数据的时候,由于没有间隙锁的存在,mysql只会锁住3和5,而这个时候有另一个事务插入了4,之后又回滚了,那么之前的查询就会查询4,而之后的查询查不到4,这就是幻读的问题。

    幻读的意思是,当一个事务执行两次,一次没有读取到的行,第二次却读取到了,那一行就称为魔幻的一行..

    // 幻读的解释

    https://dev.mysql.com/doc/refman/8.0/en/innodb-next-key-locking.html

    READ UNCOMMITTED

    比READ COMMITTED弱一级,没有锁的隔离,会导致脏读。这是由于,当某些行没有被锁住的导致其他事务可以进行更新操作,从而引发读取到脏数据。

    脏读的意思是,读取到其他事务已经修改但是还没有提交的数据。

    SERIALIZABLE

    在REPEATABLE READ的基础上,自动的加入了 'lock in share' 语句。也就是说,在select的过程中,不允许其他需要独占锁的操作发生(update等),只允许需要共享锁的操作。

    此隔离级别可以保证数据读取完整的一致性,但是级会导致所有需要独占锁的操作都变成了串行执行,性能和表锁已经没有区别了。

    参考

    mysql术语大全

    https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_dirty_read

    mysql官网对隔离性的介绍

    https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html

    表级锁和行级锁

    表级锁

    在INNODB还没出现之前,MyISAM数据库引擎只支持表级锁,包括表级共享锁和表级独占锁。

    共享锁支持多个操作同时执行,也就是并发执行,在一个操作拥有共享锁的情况下,其他操作是无法获取到独占锁的。

    独占锁只能串行执行。

    行级锁

    INNODB支持行锁,将锁定对象的粒度细化,可以增加并发性能。

    需要注意的是行级锁是建立在索引之上的,也就是说在查询没有索引的字段的情况下,还是会使用表锁。

    参考

    对MYISAM引擎和INNODB引擎很详细的对比分析

    https://baijiahao.baidu.com/s?id=1610581108528334819&wfr=spider&for=pc

    关于在非阻塞的情况下读取一致性的细节

    在INNODB的存储引擎场景下,每次查询,mysql都会给出当前表的快照,也就是说在该查询之前其他提交的事务都会被感知,而查询开始之后,其他提交的事务就不会被感知。

    举例而言

    当你select count(*) from table的时候,其实统计的是当前表的快照,不会获取任何锁,如果与此同时,有另一个插入操作,那么这两个操作是完全可以同时进行的。当然,这个结果可能不是你业务上希望看到的,可能你想要强一致性,也就是在统计数据量的时候不允许其他插入或者删除操作,那么你可以先lock table; select count(*) from table; 最后unlock table;通过表锁的方式保证数据的强一致性。

  • 相关阅读:
    tyvj[1087]sumsets
    tyvj[1089]smrtfun
    [bzoj3289]Mato的文件管理
    luogu[2093]零件分组
    luogu[1135]奇怪的电梯
    codevs[1300]文件排版
    luogu[1140]相似基因
    动态规划练习题 胖男孩
    动态规划练习题 汇率
    vijos[1355]车队过桥问题
  • 原文地址:https://www.cnblogs.com/ulysses-you/p/9602463.html
Copyright © 2020-2023  润新知