MYSQL 我说的那个锁,不是你的那个锁

深入解析MySQL锁机制
本文详细探讨了MySQL中锁的种类、加锁模式、锁的类型、粒度及隔离级别等核心概念。通过实例说明了表锁、行锁、自增锁、意向锁、间隙锁等的工作原理及相互关系,特别关注了自增锁、NEXTKEY锁和插入意向锁的特性和应用场景。

一种数据库中有很多种锁,一般说起锁都是在提,是表锁,还是行锁,有没有死锁。但实际上就算是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  这样的死锁就不会在存在了。

待......

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值