MySQL中的锁

分类

行锁&表锁

只有明确指定主键,才会执行行锁,否则执行表锁

  • 无锁

    select * from user where id = -1 for update;		
    #主键不存在
    
  • 行锁

    select * from user where id = 1 for update;
    select * from user where id = 1 and name = ‘kk‘ for update;
    #只要where后的字段建了索引,就会用行锁
    
  • 表锁

    #主键不明确
    select * from user where name = ‘kk‘ for update;
    select * from use where id <>3 for update;
    

锁算法(机制)

行锁算法

  • Record Lock(普通行锁)

    #主键值在条件范围内,单个行记录上的锁
    #记录存在
    
  • Gap Lock(间隙锁)

    #主键值不存在条件范围内,叫做间隙GAP,引擎就会对这个间隙加锁。
    #间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况
    
  • Next-key Lock(行& 间隙锁)

    #主键值一部分在条件范围内。
    #比如user表id字段自增共50条数据。
    select * from user where id >49;
    1+2,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。
    

表锁算法

  • 意向锁(升级机制)

    #当一个事务,带着表锁去访问被加了行锁的资源,此时,这个行锁就会升级为意向锁,将表锁住。
    #Session A
    select * from user where id = 1 for update ;
    #Session B
    select * from user where name like ‘kkk%‘ for update;
    那么Session A 就会升级成意向锁
    
  • 自增锁

    #事务插入自增类型的列时,获取自增锁。
    #如果一个事务正在往表中插入自增记录,其他事务都必须等待。
    

实现

共享锁 & 排他锁

行锁和表锁是粒度的概念,共享锁和排他锁是他们的具体实现。

共享锁(S)

允许一个事务去读一行,阻止其他事务去获取该行的排他锁。

select lock in share mode #MySQL 8以下版本
select for share #MySQL 8以上版本,支持nowait、skip locked,配合自旋锁可以实现等待队列。

排他锁(X):写锁

允许持有排它锁事务读写数据,阻止其他事务获取该资源的共享锁和排它锁。

select for update\insert\delete\update

多并发版本控制MVCC

加锁是当前读,保证读取的是最新的数据;在隔离级别为REPEATABLE时,不加锁的select操作是快照读,有可能读到的不是最新的版本。ps:在串行级别下,快照读会退化成当前读。

乐观锁 & 悲观锁

  • 乐观锁

    一般通过版本号进行更新检查

  • 悲观锁

    利用数据库本身提供的锁去实现

MySQL中的锁

上一篇:五分钟带你读懂 TCP全连接队列(图文并茂)


下一篇:mysql 常见统计方案整理汇总