探索Mysql锁机制(二)——共享锁&排他锁&意向锁&间隙锁

 

后面会按照下图,分批次对Mysql的锁和大家一起分享

 
image.png

🌺花絮


 
image.png

👓仔细看哦 👓
今天采蜜采到一份看起来不错的简历,正襟危坐,电话call过去。
对方的电话响着粤语版的《明年今日》,让我想起了村里的小芳,鞭子粗又长。
“喂,哪位?”,对方的声音很Young很有钱。
“同学你好,我是巴巴的面试官,你对XX巴巴有兴趣吗,现在方不方便聊聊?”。
“...你好,有啊,方便的。”
“okay,那我们简单的聊一会,你能先简单的介绍一下自己吗?”。
“好,我叫小明,在OO上班,工作3年,无房无车,有个女朋友叫清风...”
吧啦吧啦......
“项目用到了SpringBoot、MQ、Mysql...”
“好的,那我们聊一聊mysql的锁吧!”。

1. Mysql的事务


伟人说:“想了解一件事情,你就得了解它的前因后果”,
想了解透彻mysql的锁,不得不说mysql的事务机制。

于是我问小明:你对mysql的事务了解吗?
小明轻咳一下,娓娓道来:

1.1 事务概述

数据库事务是数据库执行过程中的一个逻辑单位,一个事务通常包含了对数据库的读/写操作。它的存在包含有以下两个目的:

  • 为数据库操作序列提供了一个回滚的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
  • 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法(版面问题下次讨论),以防止彼此的操作互相干扰。

1.2 事务的特性:ACID

  • 原子性 aotmic

事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。

  • 一致性 consistent

事务在完成时,必须使所有的数据都保持一致状态。

  • 隔离性 isolaton

由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状 态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据

  • 持久性 duration

事务完成后,它对系统的影响是永久性的

2. 排他锁&共享锁


我心想,这个谁都懂,继续追问:那你能在讲讲锁吗?
好的,那我讲一下Mysql的几个锁。小明窃喜,我已经看了imooc(公众号微信)大神的锁了,我怕你?

2.1 共享锁(shared locks,S锁)

小明说:在你没有女朋友的时候,你想和女人滚床单时候,只能去找红灯区,别人也可以找红灯区,这就是共享!

共享锁又叫读锁,如果事务T1对行R加上S锁,则

  • 其它事务T2/T3/Tn只能对行R再加S锁,不能加其它锁
  • 获得S锁的事务只能读数据,不能写数据(你傻呀,当然也不能删咯)。
select … lock in share mode;

2.2 排他锁(exclusive locks,X锁)

小明说:你有钱找了个女票,你就要独占这个女票,别人不能使用,看(读)都不行!这就是排他!我们重点说一下排它锁。

排它锁又叫写锁,如果事务T1对行R加上X锁,则

  • 其它事务T2/T3/Tn都不能对行R加任何类型的锁,直到T1事务在行R上的X锁释放。
  • 获得X锁的事务既能读数据,又能写数据(也可以删除数据)。
select ... for update 

举例表USER:

idnamedesc
1 马云 首富
2 小明 首负

T1(事务1):

// start T1
SELECT * FROM USER WHERE id = 1 lock in share mode; (S锁)
......

// start T2
UPDATE USER SET name = '小明' WHERE id = 1;
......

如果T1不进行提交,则S锁不会释放,
那么T2就拿着X锁眼巴巴的看着,一直等待T1(事务1)释放S锁。

此时

// 接上文代码块
// start T3
// 此时,如果 T3 做同样查询,可以直接获取S锁进行查询
SELECT * FROM USER WHERE id = 1 lock in share mode; (S锁)

这个时候如果T1(事务1)要进行 DELETE 操作

// start T1
SELECT * FROM USER WHERE id = 1 lock in share mode; (S锁)
......
DELETE FROM USER WHERE id = 1;
......

此时:
T1发现X锁被T2占据着,所以T1拿不到X锁一直等待T2释放X锁,而T2拿着X锁等待T1释放S锁,这样互相等待就产生了死锁,deadLock。
发生死锁以后,InnoDB 会产生错误信息,并且释放锁(后面会专门讲业务中遇到的死锁和解决方案)。

上述X锁的代码可以用下图来显示:

 
image.png

用时间流程来显示3个线程的交互如下:

 
image.png

 

你可以把排它锁对行的保护,看作你对你女的保护,只能你碰,别人不能动!前提你得有女,不认真学习,你就是个屌丝...单身狗

听到这里我觉得小明同学很有意思哦,这个栗子🌰举得很有力气很有代入感!不愧是有女朋友的人啊!

3. 意向锁


我对小明已经开始有点兴趣了,继续追问,那你能否再说一下意向锁?
好!

3.1 意向锁(Intention Locks)

小明说: 他在找苍老师或者女票时候,先要远程看看对方有没有被人家共享或者独占,而不是到面前有没有人锁住她,可以节省成本!

意向锁是表锁,多用在innoDB中,是数据库自身的行为,不需要人工干预,在事务结束后会自行解除。

意向锁分为意向共享锁(IS锁)和意向排它锁(IX锁)

  • 锁:表示事务中将要对某些行加S锁
  • IX锁:表示事务中将要对某些行加X锁

意向锁的主要作用是提升存储引擎性能,innoDB中的S锁和X锁是行锁,每当事务到来时,存储引擎需要遍历所有行的锁持有情况,性能较低,因此引入意向锁,检查行锁前先检查意向锁是否存在,如果存在则阻塞线程。

3.2 意向锁的使用

顺上面的思路讲下去,我们看下使用的逻辑

举个栗子🌰:

T1:
SELECT * FROM A WHERE id = 1 lock in share mode;(加S锁)

T2:
SELECT * FROM A WHERE id > 0 for update; (加X锁)

看上面这2个SQL事务,T1执行时候,对id=1这行加上了S锁,T2执行前,需要获取全表的更新锁进行判断,即:
step1:判断表A是否有表级锁
step2:判断表A每一行是否有行级锁
当数据量较大时候(我们一张表一般500-5000万数据),step2这种判断极其低效。

亚麻跌!亚麻跌!亚麻跌!于是乎,我们就need意向锁协议。

意向锁协议

  • 事务要获取表A某些行的S锁必须要获取表A的IS锁
  • 事务要获取表A某些行的X锁必须要获取表A的IX锁

Now!do you get me sense ?
这个时候step2就改变成了对意向锁的判断
step2:发现表A有IS锁,说明表肯定有行级的S锁,因此,T2申请X锁阻塞等待,不需要判断全表,判断效率极大提高(是不是省了很多钱)

4. 间隙锁


小明先飚了一段英语,想来压制我?
但是我并不care,who care?9012年了,谁不会英语?so easy!我可是从小用步步高点读机长大的人哦。
我say:pardon ? (上小学我就会,小样,你再飚啊!)

4.0 官方原文:

 

 
image.png


非常重要,必须读懂,读不懂,就去幼儿园回炉吧,亲

 

A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record. For example, SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; prevents other transactions from inserting a value of 15 into column t.c1, whether or not there was already any such value in the column, because the gaps between all existing values in the range are locked.

当我们用范围条件条件检索数据(非聚簇索引、非唯一索引),并请求共享或排他锁时,InnoDB会给符合条件的数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,称为间隙,InnoDB也会为这些间隙加锁,即间隙锁。
Next-Key锁是符合条件的行锁加上间隙锁

4.1 间隙锁产生的条件

在InnoDB下,间隙锁的产生需要满足三个条件:

  • 隔离级别为RR
  • 当前读
  • 查询条件能够走到索引

4.2 间隙锁的作用

MySQL官方文档:间隙锁的目的是为了让其他事务无法在间隙中新增数据。

在RR模式的InnoDB中,间隙锁能起到两个作用:

1. 保障数据的恢复和复制
2. 防止幻读
  • 防止在间隙中执行insert语句
  • 防止将已有数据update到间隙中

数据库数据的恢复和复制是通过binlog实现的,binlog中记录了执行成功的DML语句(在阿里得到了极广泛的应用),在数据恢复时需要保证数据之间的事务顺序,间隙锁可以避免在一批数据中插入其他事务。

对于间隙锁,笔者人为,你只要能get到上述英语片段的点,就Okay了,小学5年级就能读懂,如果读不懂,你真的要去学一下英语了,不会英语的程序员,一定是个最low逼的程序员!

转载:https://www.jianshu.com/p/904f52bde904

posted @ 2020-08-19 10:06  个性灬浪漫  阅读(1665)  评论(0编辑  收藏  举报