绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
MYSQL 我说的那个锁,不是你的那个锁
2019-09-17 16:39:36

一种数据库中有很多种锁,一般说起锁都是在提,是表锁,还是行锁,有没有死锁。但实际上就算是MYSQL 的锁的种类也不是那么简单。

实际上讨论一个锁,需要从以下几个方面来考虑

1  锁的种类   表锁  行锁

2  加锁的模式    

    LOCK_IS
    LOCK_IX
    LOCK_S
    LOCK_X
    LOCK_AUTO_INC

3  锁的类型     

4  锁的粒度

5  锁所处的隔离级别

NEXT KEY LOCK   
LOCK_GAP   
LOCK_REC_NOT_GAP   

LOCK_INSERT_INTENTION 

在知道这些东西后,才能更好的理解锁及其可能产生的各种死锁或锁超时的情况。

 

下面画了一个图,图中是MYSQL 中提供的锁的类型从图中可以看到 IS意向锁可以和除X锁的其他锁类型共存, X 锁则是和任何锁都是互斥的,和他本身也是一样,AI 锁 只和意向锁共存。

AUTO_INC 锁又叫自增锁(一般简写成 AI 锁),它是一种特殊类型的表锁,当插入的表中有自增列(AUTO_INCREMENT)的时候可能会遇到。当插入表中有自增列时,数据库需要自动生成自增值,在生成之前,它会先为该表加 AUTO_INC 表锁,其他事务的插入操作阻塞,这样保证生成的自增值肯定是的。


  • AUTO_INC 锁互不兼容,同一张表一个时刻只能有一个自增锁

  • 自增锁不遵循二段锁协议,不是事务over时release,在 INSERT 语句执行完成时释放,用以提高并发插入的性能。

  • 自增值一旦分配了就会 +1,如果事务回滚,自增值也不会减回去,所以自增值可能会出现中断的情况。


而我们熟悉的行锁

LOCK_REC_NOT_GAP   ,record 锁本身是没有那么复杂的,他仅仅对他所在的记录进行一个锁,而相关的锁,仅仅是锁在索引上边的,如果是primary key 则直接锁在主键的位置,如果是二级索引,则除了锁在二级索引上,同时还需要锁在二级索引所指定的主键上。


NEXT KEY LOCK  next key lock,顾名思义  要不是  ( ]   [ )  ,(一个集合的概念),他主要的作用是防止幻读,也就是两次读不一致的情况,所以LOCK_GAP 主要是要看所处的

隔离级别是R R  ,  RC  那两种,MYSQL 默认的隔离级别是  RR ,但一般来说强烈建议 MYSQL 的通用的使用的隔离级别是  RC 。如果我们的隔离级别是RC 级别的情况下是不会有  next key lock 这样的锁。NEXT KEY LOCK 锁会将锁定记录周围的记录也进行一个锁定。


举例:如果我们的数据表中 的数据记录是   1   6  7 8 9  10 

select  * from t where number = 6 for update

此时锁定的记录

(1 6 7),此时如果在 1和 6之间插入数据会无法插入


GAP LOCK 间隙锁,间隙锁的知名度比 NEXT KEY LOCK 要大的的

(),标识间隙锁,间隙锁本来也可以理解成为范围锁,他将防止其他事务在这个范围内插入或修改记录,保证两次读取这个范围内的记录不会变,从而不会出现幻读现象。添加间隙锁和间隙锁之间是不冲突的,而添加间隙锁会严重影响数据库的并发性,还以上面的例子来说,他是要锁定 1(23456)7 ,同时不同的事务可以在间隙上持有冲突锁。例如,事务A可以在一个gap上持有一个共享的gap锁(gap S-lock),而事务B在同一个gap上持有一个独占的gap锁(gap X-lock)。允许存在冲突的间隙锁的原因是,如果从索引中清除一条记录,则必须合并不同事务在记录中持有的间隙锁。


LOCK_INSERT_INTENTION 插入意向锁,主要是服务于插入服务的,在数据库插入的时候会诊断插入数据的位置是否有间隙锁,也就是和间隙锁next key lock 这样的锁互斥。


记录锁和记录锁冲突,Next-key 锁和 Next-key 锁冲突,记录锁和 Next-key 锁冲突;



举例我们现在有下面一张表


我们模拟两个SESSION 


1  select * from insert_lock where id <= 5 for update


2  insert into insert_lock (id,name,employee_number) values (4,'rty',12)



上边的图中可以清晰的看到  select 的查询中包含了 GAP 锁,所以GAP 锁导致 插入失败。


那如何避免上面的情况 ,直接将数据库的隔离级别从  RR 改为 RC  这样的死锁就不会在存在了。


待......



分享好友

分享这个小栈给你的朋友们,一起进步吧。

数据库杂货铺
创建时间:2021-12-10 09:57:47
分享数据库管理,运维,源代码 ,业界感受, 吐槽
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • liuaustin
    栈主

小栈成员

查看更多
  • miemieMIA
  • 578154454
  • ylfxml
戳我,来吐槽~