• Mysql的锁


    为什么要加锁?

    为了保证在并发地存取时的数据一致性。

    锁有哪些分类?

    加锁机制
    乐观锁:先修改,保存时判断是否被更新过,应用级别。
    悲观锁:先获取锁,再修改,数据库级别。

    锁粒度
    表级锁:开销小,加锁快,粒度大,锁冲突概率大,并发度低,适用于读多写少的情况。MyISAM存储引擎。
    页级锁:bdb存储引擎。
    行级锁:Innodb存储引擎,默认选项。

    兼容性
    S锁:也叫读锁、共享锁,对应于 select * from users where id =1 lock in share mode
    X锁:也叫写锁、排它锁、独占锁、互斥锁,对应于 select * from users where id =1 for update (记录锁、间隙锁、临键锁都是排它锁)

    锁模式
    记录锁(Record Locks):封锁一个索引记录,也叫行锁,其他事务只能读被锁的记录,不能insert、update、delete。
    间隙锁(Gap Locks):封锁索引记录中的间隔,或者查询到的第一条索引记录之前的范围,又或者查询到的最后一条索引记录之后的范围。
    (1)多个事务可以获得同一个gap的间隙锁,间隙锁的唯一目的就是防止在间隙中insert数据。
    (2)共享间隙锁与排他间隙锁没有区别。

    临键锁(Next-key Locks):是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。
    (1)临键锁主要是为了避免幻读。如果把事务的隔离级别降级为RC,临键锁则会失效。

    意向锁(Intention Locks):简单来说是帮助更快地判断当前表加了什么样的行锁。如果另一个任务试图在该表级别上应用S或X锁,则受到由第一个任务控制的表级别意向锁的阻塞。第二个任务在锁定该表前不必检查各个页或行锁,而只需检查表上的意向锁。(两S兼容,两I兼容)

    插入意向锁(Insert Intention Locks):该锁用以表示插入意向,当多个事务在同一区间(gap)插入位置不同的多条数据时,事务之间不需要互相等待(允许并发insert)。 插入意向锁是一种间隙锁,但它不妨碍多个事务同时insert,多个插入意向锁可以兼容。但此时如果有事务要进行加间隙锁的查询,需要等待,不是因为间隙锁和插入意向锁冲突,而是因为insert操作和间隙锁是冲突的。
    例1:假设已有数据4和7,有A、B线程分别要插入5、6。A、B线程先分别获得4~7这个间隙的插入意向锁,然后各自插入数据,A线程获得数据5的记录锁,B线程获得数据6的记录锁。
    例2:A线程查询数据并获得4~7的间隙锁,此时B线程想插入数据6,B线程可以获得4~7的插入意向锁,但B线程需要等待A释放间隙锁,才可以insert加记录锁。

    不同SQL语句加的锁(有待研究)
    (1)普通select
    在4个事务隔离级别中,除了在串行化(Serializable)时会加共享锁,其他的都不加锁。
    因为MySQL(InnoDB)支持MVCC,对普通select语句能够进行快照读,很好地支持了读写并发。
    (2)显式加锁select
    select ... for update(加互斥锁)
    select ... in share mode(加共享锁)
    (要在事务中使用这些锁,否则不在事务中是没有意义的)

    聚集索引等值查询
    聚集索引上:记录锁 select * from user where id=10 for update
    唯一索引(非聚集索引)等值查询
    聚集索引上:记录锁
    辅助索引(唯一索引)上:记录锁

    非唯一索引等值查询
    聚集索引:记录锁
    辅助索引:临键锁(记录锁 + 间隙锁)
    select * from user where name=‘b’ for update

    无索引查询
    表级锁
    记录不存在

    相应索引:间隙锁
    要保证没有其他人可以插入,所以锁住间隙

    (3)隐式加互斥锁update和delete

    (4)普通insert
    (插入区间)聚集索引:插入意向锁
    (插入记录)聚集索引:记录锁
    insert into child (id) values (90),(102);
    (5)先select后insert
    (插入区间)聚集索引:插入意向锁
    (插入记录)聚集索引:记录锁
    (select的源表)聚集索引:共享的临键锁。这是为了防止主从同步出问题。
    insert into target_table select * from source_table ...
    create target_table select * from source_table ...
    #将select查询的结果集,插入到另一张表中,或者使用结果集,创建一个新表。

  • 相关阅读:
    django+xadmin在线教育平台慕学网(一)
    django.db.migrations.exceptions.InconsistentMigrationHistory django报错
    mac系统 MySQL 8.0.11版本,安装成功,使用Navicat连接失败
    MySQL-表操作
    MySQL的数据类型
    存储引擎
    库操作
    MySQL学习目录
    初识MySQL数据库
    静态方法和类方法
  • 原文地址:https://www.cnblogs.com/shijianchuzhenzhi/p/12416651.html
Copyright © 2020-2023  润新知