MySQL的锁(总结篇)

·  阅读 69

参考资料:MySQL的锁(完整篇)

MySQL数据库包含各种锁,为方便了解,我们按照分类逐个简单介绍。

按照是否允许同时访问

对于某行记录,会存在多个事务同时访问的情况,我们可以分为共享锁和独占锁

共享锁

英文名:Shared Locks,简称:S锁。顾名思义,允许多个事务同时共享数据。

加锁方式:

select * from t where id = 1 lock in share mode;
复制代码

当事务A访问记录1时,先给记录1加个共享锁;接着,事务B也打算访问记录1,此时也加个共享锁,允许访问。

独占锁

英文名:Exclusive Locks,简称:X锁。顾名思义,仅允许一个事务访问记录。

加锁方式:

select * from t where id = 1 for update;
复制代码

当事务A访问记录1时,先给记录1加个独占锁;接着,事务B打算访问记录1,无论事务B想加S锁还是X锁,都要阻塞等待事务A提交后才可以访问记录1。

各种情况加锁

  • 假设记录1没有加锁,事务A过来加个S锁。接着,事务B姗姗来迟,如果它加S锁,没问题,可以访问;如果它加X锁,那得等事务A提交完才可以访问
  • 假设记录1没有加锁,事务A过来加个X锁。接着,事务B姗姗来迟,无论它加S锁还是X锁,都得等事务A提交才可以访问

image-20201127160318729

按照锁的颗粒度

按照锁的颗粒度,可以分为表锁和行锁。除此以外,为了保证事务的隔离级别,还诞生了意向锁、间隙锁等等。

表锁

表锁,Table Locks,顾名思义,锁定整个表里面的所有记录,会分为表共享锁和表独占锁。

加锁方式:

# 共享锁
LOCK TABLES t READ;
# 独占锁
LOCK TABLES t WRITE;
复制代码

兼容性:

  • 如果一个事务给表加了共享锁,其他事务可以同样加共享锁,但是不能加独占锁
  • 如果一个事务给表加了独占锁,其他事务不可以加任何锁

行锁

行锁,Record Locks,顾名思义,锁定某行记录。同样,也会分S锁X锁,加锁方式就不再赘述。

意向锁

试想一个情景:事务A过来给加个独占锁,那么它得确认表中所有记录都没有加锁,这样它才可以加锁成功。怎么确认呢,逐行遍历吗??当然不是啦,为了快速判断这个表的记录有没有被锁定,诞生了意向锁的概念。

如果事务B需要对记录1加独占锁,那么先要获取这个表的意向独占锁;如果需要对记录1加共享锁,那就先获取这个表的意向共享锁。因此,当事务A需要加表锁时,根据这个表的意向锁就可以判断行记录的锁状态。

意向锁,Intension Lock,分为IS锁IX锁


以上,把基本的锁介绍完毕,但是为了解决幻读的问题,InnoDB还有间隙锁、Next-Key锁。接下来,也把它们介绍完

间隙锁

MySQL在可重复读的隔离级别下,是可以解决幻读问题的。解决方法有两个,一个是MVCC方案解决,一个是采用加锁方式(至于使用哪种方式,要具体分析,暂时没了解)。由于幻读是指在查询条件相同时,重复查询,会读取到之前没有的数据。为此,官方提出了间隙锁的概念。

间隙锁,Gap Locks

来个栗子:下图所示,给number值为8的行记录加了间隙锁,意味着不允许其他事务在这条记录前面的间隙插入新纪录,也就是(3,8)区间不能新增记录。

image-20201127163057212

间隙锁的提出,仅仅是为了防止插入幻影记录而提出的。

Next-Key Locks

Next-Key Locks就是行锁+间隙锁,既锁定当前记录,又禁止在当前记录前的间隙中插入新纪录。

image-20201127163517538

意向插入锁

事务在插入记录时,先判断插入位置是不是被其他事务加了gap锁,如果有的话,需要在内存结构中生成一个锁结构,表明有个事务想在折这个间隙插入记录。这种锁就是Insert Intension Locks,插入意向锁。

image-20201127164648620

分类:
后端
标签:
分类:
后端
标签: