mysql锁系列之MDL元数据锁之三

版权声明:本文章为博主原创文章,未经博主允许不得转载,如有问题,欢迎留言交流指正 https://blog.csdn.net/finalkof1983/article/details/88247329

基础材料:

centos7.5  mysql 5.7.24


前一篇说明了元数据锁的相关加锁顺序,今天再结合online DDL更深入的研究一下这个加锁顺序究竟如何。

这里先简单说明一下online DDL锁升降级的过程,大体分为三步:

1、准备阶段:将申请到的SHARED_UPGRADABLE读锁升级为EXCLUSIVE写锁。禁止读写。

2、执行阶段:将EXCLUSIVE写锁降级成SHARED_UPGRADABLE读锁。期间可读写。

3、提交阶段:将SHARED_UPGRADABLE读锁升级为EXCLUSIVE写锁。禁止读写。


下面进行一个实验,用来毁三观,将<mysql锁系列之MDL元数据锁之一>中的实验改为如下,将id 45做成事务,不提交:

id 41 id 42 id 43 id 44 id 45
  begin; begin; alter table testok add z varchar(10) not Null; begin;
  select * from testok limit 1; select * from testok limit 1;   select * from testok;

 此时提交id 42,43,后会发现id 45的语句执行完了,id 44仍然被卡住等待EXCLUSIVE写锁,和开始一样一点没变。话说之前写的可是,写锁优先,且阻塞后续操作的啊,为啥id 45先执行了,44没动,这是不是有问题?

首先说明前面说的加锁规则并没有问题,当id 42,43执行完成后,id 44确实执行了,会在准备阶段拿到EXCLUSIVE写锁,此时id 45被pending。但在id 44执行阶段会进行锁降级,同为读锁,则id 45可以获取该锁,且持有该锁。当id 44运行到了提交阶段,要进行锁升级,此时需要等待id 45的读锁释放,被pending。观察的直观现象就是id 45执行完了,id 44好像没动。

如果id 45 执行的是lock tables testok read;select ....lock in share mode;select...for update则表现的情况与上面相同。

如果id 45 执行的是lock tables testok write;则id 44先执行完成并提交,id 45使用排他锁锁住该表。

如果id 45 执行的是alter table xxx,则id 45一直等待id 44的SHARED_UPGRADABLE锁释放,直到id 44执行完成。

猜你喜欢

转载自blog.csdn.net/finalkof1983/article/details/88247329