美文网首页
MySQL - 锁

MySQL - 锁

作者: DjangoW | 来源:发表于2018-08-15 16:59 被阅读0次

    1. 锁

    提到锁,一般都是因为存在竞争条件(Race Condition)而导致结果不可预测。比如两个线程同时修改某个值,最终这个值的结果是什么有多种可能性。如果加入锁,在线程访问修改某个值的时候,可以禁止其他线程同时访问修改这个值,这样就避免了多种结果的可能性。

    MySQL Innodb的锁的最小单位是行锁,基于索引(Index)实现,加锁的时候是在B+树索引结构的节点上加锁。所以如果某个字段没有索引,然后用户通过这个字段进行查找来更新数据的时候就会导致整个表(其实是整个聚类索引的叶子结点)被加锁;如果用户通过聚类索引的字段进行查找,则只对索引查找结果的叶子节点加锁;如果用户通过二级索引字段进行查找,则除了对二级索引加锁,还会对聚类索引加锁。

    2. 事务

    事务具有ACID特性:分别是原子性(atomicity),一致性(consistency),隔离性(isolation),和持久性(durability)
    原子性(atomicity)是指一个事务内的操作要不全被commit,要不整个rollback。
    一致性(consistency)是指系统始终处于一致的状态,事务操作只会使系统从一个状态变幻到另一个一致的状态。
    隔离性(isolation)是指各个事务之间是独立的,隔离的,彼此不会相互影响。
    持久性(durability)是指事务提交之后数据持久保存在数据库系统中。

    3. 数据库的隔离级别

    数据库的隔离级别(Isolation level)分为:未提交读(Uncommit Read),提交读(Commit Read),可重复读(Repeatable Read)和可串行化(Serializable)

    在了解隔离级别之前先来看看InnoDB读的分类:快照读(snapshot read)现读(current read)
    一般的SELECT都是快照读,其他的读都属于现读,比如SELECT * FROM tableName FOR SHARE。快照读不加锁,根据隔离级别的不同读取策略也不同;现读会加S锁(共享锁)或者X锁(互斥锁),其中SELECT ... FOR SHARE会加S锁,其他情况都是加X锁。

    未提交读(Uncommit Read)就是快照读可以读取事务内修改了但是未提交的值,这种情况下就会产生脏读。一般不会考虑设置为数据库隔离级别。
    提交读(Commit Read)就是快照读只可以读取提交之后的数据。这样就消除了脏读的产生,但是会有幻读产生的可能性。所谓幻读就是本来要修改了年龄等于20的用户的表信息,事务提交之后发现有些“没有修改成功”,因为有线程在上述事务期间插入了年龄为20的新用户信息,这样会有一种操作未成功的错觉。是MySQL的默认隔离级别。
    可重复读(Repeatable Read)的隔离级别下除了一般的行锁,也会同时加上间隙锁(gap lock)。间隙锁防止了幻读的产生:上例中age为20的B+树节点之间和范围前后节点之间也会被加锁,导致age为20的新数据无法插入。
    可串行化(Serializable)的隔离级别下,快照读不复存在,所有的读都是现读。读写冲突,导致性能下降。一般不会考虑设置为数据库隔离级别。

    4. 死锁以及如何避免死锁

    Reference

    hedengcheng.com/?p=771

    相关文章

      网友评论

          本文标题:MySQL - 锁

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