开发者学堂课程【MySQL 实操课程:InnoDB 下锁的类型】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/717/detail/12818
InnoDB 下锁的类型
内容介绍
一、读锁
二、写锁
三、MDL 锁
一、读锁
1、读锁,简称S锁,一个事务获取了一个数据行的读锁,其他事务能获得改行对应的读锁,但不能获得写锁,即一个事务在读取一个数据行时,其他事务也可以读,但不能对该数据行进行增删改的操作。
2、MySQL 使用 select…Lock in share mode 在被读取的行记录或行记录的范围上加一个读锁,让其他事务可以读,但是要想申请加写锁,那就会被阻塞。
举例图示:
图一:
图二:
图一是 in no DB 的存储引擎,图二是需要给id=6的用户加上对应的读锁;图一可以看作并发,或者一个客户端,在里面执行如图二的读锁,那么在客户端进行更新便会被阻塞,如若查询,便可执行。锁上的是整个表,这便是读锁。
(1)接下来进行演示:
首先进入shell表中,输入“select*from user”,其次输入“unlock tables”,再输入“elect*from user-bak where id=2”,在进行执行,紧接着再输入“select*from user”执行,如图:
可以观察到这是 in no DB 的存储引擎。
操作完以上步骤后,在输入“being”,输入“update user bak set name=‘zhangsan’where id=1”,输入“select*from user where id=1”,这样是可以的,同时在另一边进行写操作也是可行的,因为在第一页并没有进行上锁,只有查询的执行命令,所以在第二页是可以进行改写的。
(2)如何上读锁
输入“select*from user where id=1 look in share mode”,输入之后便会执行;为什么代码会阻塞?因为接着执行了update,便上了隐示的锁,当再次执行读锁时,便会被阻塞。
为了演示方便,不再重头开始演示,输入“roll back”,“being”,现在已经去掉了读锁,再在两边执行select,这样是没有问题的;要是此时返回第一页,在第一页执行update,会被阻塞,此时不管改写任何参数,都是行不通的,这里是被上了表锁,这个知识点在后面会讲到。
(3)读锁的另一种的写法
输入“select*from user where id=1 for update”后执行“being”,另一页内输入“update user set name=‘zhangsan1’where id=2”再输入“being”,这便是ln no DB下的读锁。
二、写锁
1、写锁,简称X锁,一个事务获取了一个数据行的写锁,其他事务就不能再获取改行的其他锁;
2、写锁优先级最高。如一些DML语句的操作会对行记录加写锁;
3、下面实验事务隔离级别为(read committed)。
(1)举例图示:
图三:
图四:
图三开启了事物,在执行 update 一行的 select 语句时,会给user表增加写锁,是隐示的,写锁并不会跟读锁一样需要手动添加,写锁在执行语句时会自动添加写锁;图四中是可以进行查询的,并且不再支持写。
(2)演示:
①首先给图三开启事物,确定两边的事物都进行了回滚,输入“update user set name=‘zhangsan1’where id=1”就已经给此表上了写锁,接下来在另一边同样开启事物,出现了一点失误,网络断开了,输入“ssh root”加上内网地址重新进入,两边都如此。然后连接MySQL的客户端,再清屏;回到刚刚的例子,使用阿里云,再输入“being”,“update user set name=‘zhangsan1’where id=1”,此时已经加上了隐示写锁,如图:
②可以观察到被阻塞,虽然之前断开了链接,但是锁依然存在,遇到这种情况大家可以把MySQL重新启动,输入“/usr/local/mysql/bin/mysql admin shutdown-u root-p”后再执行“mysql d-safe/etc/my. cnf”,执行之后再连接阿里云,执行“being”,“update user set name=‘zhangsan1’where id=1”,可以发现此时没有锁的存在了,第一页会添加隐示的锁;接着在第二页进行同样的操作,执行“being”,输入“select*from user where id”,如图:③查询是没有问题发生的,再在第一页执行“update user set name=‘zhangsan1’where id=1”,如图所示:
④很明显行不通,这是被隐示的添加写锁后的形式,在表中输入“roll back”,便会回到之前的表,这便是写锁。
⑤演示的环境是测试的环境,当前使用的是可重复读的,在 read committed 环境中也是可以的。
4、写锁的另一种写法
select for update,它会对读取的行记录上加一个写锁,那么其他任何事务就不能对锁定的行上加任何锁了,要不然会被阻塞。如在查询数据时,不希望被其他的客户端改写数据,便可加上写锁,通过 for update 的方式。
举例图示:
可以进行查询,但是不能进行改写。
三、MDL 锁
1、Meta data lock,简称 MDL 锁,用于保证表中元数据的信息。
2、在图五中,表开启了事务后,会自动获得一个 MDL 锁,图六就不可以执行任何DDL语句的操作。
(1)举例图示:
图五:
图六:
当在图五表中开启事务后,会自动获得一个MDL锁,图六就不可以执行任何DDL语句的操作,也就是说,当表中有涉及到DDL的语句时,都会被阻塞。
(2)演示:
在第一页执行“being”,““update user set name=‘zhangsan2’where id=1”,执行后再输入“select*from user”,此时没有问题出现,如图:
如果此时在表中输入“alter table user add num tiny int(1)not null default0”,再点击回车,可以观察到会被阻塞。所以在开启事物时,会自动增加 MDL 的元数据锁,这便是元数据锁的用法;接着执行 roll back,DDL 语句会被执行,元数据锁一旦有新事物的开启,便会添加锁,并会阻塞语句的执行。
以上便是 ln no DB D 的所有内容。











