开发者学堂课程【MySQL 实操课程:InnoDB 下行级别锁种类】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/717/detail/12819
InnoDB 下行级别锁种类
内容简介
一、In no DB 下行级别锁种类
二、间隙
接下来学习第三部分的内容,ln no DB 下行锁的种类,一共提供了两种,分别是共享锁和排查锁,共享锁也叫读锁,排查锁也叫写锁。在执行查询语句或更新语句时,为了受影响的记录,施加行记锁的方法很简单。如何施加行记锁?第一种方式是施加共享锁,第二种方式是 for update,另外还有在执行一些更新时,会自动帮助增加排查锁。
一、In no DB 下行级别锁种类
1、行记录锁准备工作
(1)修改表结构,添加一列 score,并对score列进行赋值。
(2)确认当前事务的隔离级别为 MySQL 默认的可重复读 (repeatable read)
①举例图示:
②演示:
在表中增加字段,执行“alter table user add score int(2)not null default0”,再查询此表,输入“select*from user”,详情如下图:
可以看到字段已经成功加入,这是准备工作。
2、行记录锁实战
(1)分别开启两个 MySQL 客户端 session1 和 session2,并确认事务隔离级别为repeatable read;
(2)在 session1 中,表开启了事务后,更新 score 为90的记录;
(3)在 session2 中更新 score 为80的记录发现也被阻塞,出现锁等待,直至超时。
①举例图示:
session1:
session2:
②演示:
第一步:表已经增加过了,输入“select*from user”,“being”,先把值进行改写,因为 score 里面是没有数据的,更新下数据,输入“update user set score=70 where id=1”,id 为2的 score 值改为80,id 为3的 score 值改为90,在执行“select*from user”,详情如下:
里面便有了值,接下来执行“roll back”,“being”,再执行“update user set name=‘zhouba’where score=90”,意思是把表中的 id3wangwu 改成 zhouba, 点击回车;在另一边也是如此,在第二页执行更改后的 score值也行不通,因为前面有锁表的操作,可以观察到所有的操作都未生效.
第二步:先添加索引,执行“create index idx- score on user(score)”语法,此时此索引创建成功,在执行“show indexes from user”,详情如下:
可以看到一个索引,目录为普通索引,再输入“being”,执行前面的操作,另一边也是如此,两边都执行“update user set name=‘zhouba’where score=90”,直接被执行成功,因为两边都是执行的 score,如下图:
此图未成功执行的原因,score 数据在之前改之后进行了回滚,此处重新进行定义,导致锁未加上的原因,需要确定数据成功更改,接着吧 id 为1的 score 值改为70,id 为2的 score 值改为80,id 为3的值改为90,执行结果如下:
此时已经拥有了索引,为了重新演示,需要删除参数,表中无索引即可,在查询此表,输入“create index idx- score on user(score)”,点击回车,引进之后便有了索引。
再进行 update,执行 score 值为90的,可以看到并不能执行,因为已经被阻塞,此时返回查询值是否还存在,确认之后在加上索引,再确定“show indexes from user”表是否有索引,输入“being”,另一边同样的操作,然后添加 update 语句,另一边添加 update 语句会被阻塞,在阻塞的一边改值为80,便会成功执行。
可以发现索引在此环境下会生效,之前的操作相当于在 score 表上添加了列,加的是索引列。如果改动的值是“update user set name=‘zhouba’where id=3”,不管是 id3 还是id2同样会被阻塞,主要是因为 was 条件后的字段需要添加索引;
写法“update user set name=‘zhouba’where score=90and id=3”和“update user set name=‘zhouba’where id=3 and score=90”同样被阻塞,演示发现“update user set name=‘zhouba’where id=2and score=80”,可以执行。
第三步:在 was 查询条件后需添加索引和字段,加锁实际上是对索引加锁,如果不给索引加锁,便会使用默认的表记锁,这样会降低 ln no DB 表的并发性能,所以一定要加索引链。
二、间隙锁
1、在RR这个事务隔离级别,为了避免幻读现象,引入了 Gap lock。它只锁定行记录数据的范围,不包含记录本身,即不允许在此范围内插入任何数据;
2、间隙锁的列所建立的索引必须为唯一索引
(1)演示:
首先需要创建间隙锁的索引,“create unique index ide x_ user_ score on user(score);begin”,在表中输入“roll back”,执行“drop index ide x_ user_ score on user”“show indexes on user”“show indexes from user”可以观察到无任何索引,接着创建一个唯一索引后输入“show indexes from user”查询,执行结果如下:
在输入“being”“select*from user where score<80look in share mode”,如图:
现在一共有三条记录,之后再在另一边执行“being”“insert into user (id, name,score)values (4,sunqi,95)”,输入“select*from user”进行查询,结果如下:
可以观察到已经成功插入,再插入一个值看执行结果,输入“being”“insert into user (id, name,score)values (5,wujiu,55)”,此时被阻塞到,因为前面进行了小于80的锁,小于80的是插不进的,大于等于80的才可以,大家把此锁成为间隙锁。
(2)不满足以上两个条件,再演示第三种看是否会被阻塞
在表中输入“set sessin transaction level read committed” “set sessin transaction isolation level read committed”“show variables like ‘tx-isolation’”,
一顿操作后,数据还未进入到表中,表中的数据还是原始数据,两边的操作基本相同,两边设置完之后,在重复演示,值在输入中一条一条加入,这种做法是完全失效的,所以只有事物是可重复读并是唯一索引时,才能成功插入。
本节课主要讲了三大板块,第一板块讲的 MySQL 下不同存储引擎下的不同形式讲了 MySQL 引擎和 ln no DB 引擎,MySQL 需要手动加锁,包括读锁和写锁,加锁之后去执行其他未加锁的表,当前客户端会报出错误;第二板块讲的 ln no DB 下锁的类型,读锁和写锁也演示过了;第三板块讲的 ln no DB 下行级锁的种类,也讲了 ln no DB 下行锁的要求,需要加索引,并包括讲的元数据锁、MDL,这节课到此结束。













