MDL锁的概念和分类

1、MDL类型

锁名称

锁类型

说明

适用语句

MDL_INTENTION_EXCLUSIVE

共享锁

意向锁,锁住一个范围

任何语句都会获取MDL意向锁,

然后再获取更强级别的MDL锁。

MDL_SHARED

共享锁,表示只访问表结构

MDL_SHARED_HIGH_PRIO

共享锁,只访问表结构

show create table 等

只访问INFORMATION_SCHEMA的语句

MDL_SHARED_READ

访问表结构并且读表数据

select语句

LOCK TABLE ...  READ

MDL_SHARED_WRITE

访问表结构并且写表数据

SELECT ... FOR UPDATE

DML语句

MDL_SHARED_UPGRADABLE

可升级锁,访问表结构并且读写表数据

Alter语句中间过程会使用

MDL_SHARED_NO_WRITE

可升级锁,访问表结构并且读写表数据,并且禁止其它事务写。

Alter语句中间过程会使用

MDL_SHARED_NO_READ_WRITE

可升级锁,访问表结构并且读写表数据,并且禁止其它事务读写。

LOCK TABLES ... WRITE

MDL_EXCLUSIVE

写锁

禁止其它事务读写。

CREATE/DROP/RENAME TABLE等DDL语句。

2.按对象/范围维度划分

属性

含义

范围/对象

GLOBAL

全局锁

范围

COMMIT

提交保护锁

范围

SCHEMA

库锁

对象

TABLE

表锁

对象

FUNCTION

函数锁

对象

PROCEDURE

存储过程锁

对象

TRIGGER

触发器锁

对象

EVENT

事件锁

对象

3.按请求/释放锁持续时间划分

属性

含义

MDL_ STATEMENT

语句级别

MDL_TRANSACTION

事务级别

MDL_EXPLICIT

需要显示释放

4.MDL锁类型的兼容性矩阵

5.MDL Lock实现分类

  • scope lock:一般对应全局 MDL Lock,如 flush table with read lock 会获取namespace space:GLOBAL type:S和namespace space:COMMIT type:S的MDL Lock。它包含 GLOBAL, COMMIT, TABLESPACE 和 SCHEMA
  • object lock:如其名字所示,对象级别的 MDL Lock,比如 TABLE 级别的 MDL Lock,这也是本文的讨论核心。它包含其他的 namespace。
##源码注释
/**
Helper struct which defines how different types of locks are handled
for a specific MDL_lock. In practice we use only two strategies: "scoped"
lock strategy for locks in GLOBAL, COMMIT, TABLESPACE and SCHEMA namespaces
and "object" lock strategy for all other namespaces.
*/

6.MDL Lock duration(MDL Lock 持续周期)

这个对应源码的 enum_mdl_duration,通常我们需要关注 MDL Lock 是事务提交后释放还是语句结束后释放,实际上就是这个,这对 MDL lock 堵塞的范围很重要。我直接复制源码的解释。

  • MDL_STATEMENT:Locks with statement duration are automatically released at the end of statement or transaction.
  • MDL_TRANSACTION:Locks with transaction duration are automatically released at the end of transaction.
  • MDL_EXPLICIT:Locks with explicit duration survive the end of statement and transaction.They have to be released explicitly by calling MDL_context::release_lock().

7.对于INSERT INTO T SELECT ... FROM S WHERE ...

在RR隔离级别下,会对S表查到的行执行lock next-key;在RC隔离级别下,则不会加锁。

常见 MDL Lock 类型加锁测试

1、MDL_INTENTION_EXCLUSIVE(IX)

这个锁会在很多操作的时候都会出现,比如做任何一个 DML/DDL 操作都会触发,实际上 DELTE/UPDATE/INSERT/FOR UPDATE 等 DML 操作会在 GLOBAL 上加IX锁,然后才会在本对象上加锁。而 DDL 语句至少会在 GLOBAL 上加IX锁,对象所属 SCHEMA 上加IX锁,本对象加锁。

下面是 DELETE 触发的 GLOABL IX MDL LOCK:

2017-08-03T18:22:38.092205Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T18:22:38.092242Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T18:22:38.092276Z3[Note] (--->MDL PRINT) Namespaceis:GLOBAL
2017-08-03T18:22:38.092310Z3[Note] (---->MDL PRINT) Fast path is:(Y)
2017-08-03T18:22:38.092344Z3[Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX)
2017-08-03T18:22:38.092380Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_STATEMENT
2017-08-03T18:22:38.092551Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY

我们注意一样它的持续周期为语句级别。

下面是 ALETER 语句触发的 GLOABL IX MDL Lock:

2017-08-03T18:46:05.894871Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T18:46:05.894915Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T18:46:05.894948Z3[Note] (--->MDL PRINT) Namespaceis:GLOBAL
2017-08-03T18:46:05.894980Z3[Note] (---->MDL PRINT) Fast path is:(Y)
2017-08-03T18:46:05.895012Z3[Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX)
2017-08-03T18:46:05.895044Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_STATEMENT
2017-08-03T18:46:05.895076Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY

所以这个 MDL Lock 无所不在,而只有是否兼容问题,如果不兼容则堵塞。scope lock 的 IX 类型一般都是兼容的除非遇到 S 类型,下面讨论。

2、MDL_SHARED(S)

这把锁一般用在 flush tables with read lock 中,如下:

MySQL> flush tables with read lock;
Query OK, 0 rows affected (0.01 sec) 2017-08-03T18:19:11.603911Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T18:19:11.603947Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T18:19:11.603971Z3[Note] (--->MDL PRINT) Namespaceis:GLOBAL
2017-08-03T18:19:11.603994Z3[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED(S)
2017-08-03T18:19:11.604045Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_EXPLICIT
2017-08-03T18:19:11.604073Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY
2017-08-03T18:19:11.604133Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T18:19:11.604156Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T18:19:11.604194Z3[Note] (--->MDL PRINT) Namespaceis:COMMIT
2017-08-03T18:19:11.604217Z3[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED(S)
2017-08-03T18:19:11.604240Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_EXPLICIT
2017-08-03T18:19:11.604310Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY

我们注意到其 namspace 为 GLOBAL 和 COMMIT 显然他们是 scope lock,他们的 TYPE 为 S,那么很显然根据兼容性原则 scope lock 的 MDL IX 和 MDL S 不兼容,flush tables with read lock 就会堵塞所有 DELTE/UPDATE/INSERT/FOR UPDATE 等 DML 和 DDL 操作,并且也会堵塞 commit 操作。

3、MDL_SHARED_HIGH_PRIO(SH)

这个锁基本上大家也是经常用到只是没感觉到而已,比如我们一般 desc 操作。

兼容矩阵如下:

操作记录如下:

MySQL> desc test.testsort10;

2017-08-03T19:06:05.843277Z4[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T19:06:05.843324Z4[Note] (>MDL PRINT) Thread id is4:
2017-08-03T19:06:05.843359Z4[Note] (->MDL PRINT) DB_name is:test
2017-08-03T19:06:05.843392Z4[Note] (-->MDL PRINT) OBJ_name is:testsort10
2017-08-03T19:06:05.843425Z4[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T19:06:05.843456Z4[Note] (---->MDL PRINT) Fast path is:(Y)
2017-08-03T19:06:05.843506Z4[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_HIGH_PRIO(SH)
2017-08-03T19:06:05.843538Z4[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T19:06:05.843570Z4[Note] (------->MDL PRINT) Mdl status is:EMPTY

这中类型的优先级比较高,但是其和 X 不兼容。注意持续时间为 MDL_TRANSACTION。

4、MDL_SHARED_READ(SR)

这把锁一般用在非当前读取的 select 中。

兼容性如下:

操作记录如下:

MySQL> select* from test.testsort10 limit 1;

2017-08-03T19:13:52.338764Z4[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T19:13:52.338813Z4[Note] (>MDL PRINT) Thread id is4:
2017-08-03T19:13:52.338847Z4[Note] (->MDL PRINT) DB_name is:test
2017-08-03T19:13:52.338883Z4[Note] (-->MDL PRINT) OBJ_name is:testsort10
2017-08-03T19:13:52.338917Z4[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T19:13:52.338950Z4[Note] (---->MDL PRINT) Fast path is:(Y)
2017-08-03T19:13:52.339025Z4[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ(SR)
2017-08-03T19:13:52.339062Z4[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T19:13:52.339097Z4[Note] (------->MDL PRINT) Mdl status is:EMPTY

这里还是要提及一下平时我们偶尔会出现 select 也堵住的情况(比如 DDL 的某个阶段需要对象 MDL X 锁)。我们不得不抱怨 MySQL 居然会堵塞 select 其实这里也就是 object mdl lock X 和 SR 不兼容的问题(参考前面的兼容矩阵)。注意持续时间为 MDL_TRANSACTION。

5、MDL_SHARED_WRITE(SW)

这把锁一般用于 DELTE/UPDATE/INSERT/FOR UPDATE 等操作对 table 的加锁(当前读),不包含 DDL 操作,但是要注意 DML 操作实际上还会有一个 GLOBAL 的 IX 的锁,前面已经提及过了,这把锁只是对象上的。

兼容性如下:

操作记录如下:

MySQL> select* from test.testsort10 limit 1for update;

2017-08-03T19:25:41.218428Z4[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T19:25:41.218461Z4[Note] (>MDL PRINT) Thread id is4:
2017-08-03T19:25:41.218493Z4[Note] (->MDL PRINT) DB_name is:test
2017-08-03T19:25:41.218525Z4[Note] (-->MDL PRINT) OBJ_name is:testsort10
2017-08-03T19:25:41.218557Z4[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T19:25:41.218588Z4[Note] (---->MDL PRINT) Fast path is:(Y)
2017-08-03T19:25:41.218620Z4[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_WRITE(SW)
2017-08-03T19:25:41.218677Z4[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T19:25:41.218874Z4[Note] (------->MDL PRINT) Mdl status is:EMPTY

注意持续时间为 MDL_TRANSACTION 。

6、MDL_SHARED_WRITE_LOW_PRIO(SWL)

这把锁很少用到源码注释只有如下:

Usedby DML statements modifying tables andusing the LOW_PRIORITY clause

不做解释了。

7、MDL_SHARED_UPGRADABLE(SU)

这把锁一般在 ALTER TABLE 语句中会用到,他可以升级为 SNW、SNRW、X,同时至少 X 锁也可以降级为 SU,实际上在 Innodb ONLINE DDL 中非常依赖它,由于它的存在那么 DML(SW) 和 SELECT(SR) 都不会堵塞。

兼容性如下:

我们有必要研究一下他的兼容性,可以看到 OBJECT LOCK 中 (SELECT)SR 和 (DML)SW 都是允许的,而在 SCOPED LOCK 中虽然 DML DDL 都会在 GLOBAL 上锁,但是其类型都是 IX。所以这个 SU 锁不堵塞 DML/SELECT 读写操作进入 Innodb 引擎层,它是 ONLINE DDL 的基础。如果不兼容你都进入不了 Innodb 引擎层,更谈不上什么 ONLINE DDL,注意我这里说的 ALGORITHM=INPLACE的ONLINE DDL。

操作日志记录:

MySQL> alter table testsort12 add column it intnotnull;
Query OK, 0 rows affected (6.27 sec)
Records: 0Duplicates: 0Warnings: 0
2017-08-03T19:46:54.781453Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T19:46:54.781487Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T19:46:54.781948Z3[Note] (->MDL PRINT) DB_name is:test
2017-08-03T19:46:54.781990Z3[Note] (-->MDL PRINT) OBJ_name is:testsort12
2017-08-03T19:46:54.782026Z3[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T19:46:54.782060Z3[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_UPGRADABLE(SU)
2017-08-03T19:46:54.782096Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T19:46:54.782175Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY
2017-08-03T19:46:54.803898Z3[Note] (upgrade_shared_lock)THIS MDL LOCK will upgrade
2017-08-03T19:46:54.804201Z3[Note] (upgrade_shared_lock)THIS MDL LOCK upgrade TO
2017-08-03T19:46:54.804240Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T19:46:54.804254Z3[Note] (->MDL PRINT) DB_name is:test
2017-08-03T19:46:54.804267Z3[Note] (-->MDL PRINT) OBJ_name is:testsort12
2017-08-03T19:46:54.804280Z3[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T19:46:54.804293Z3[Note] (----->MDL PRINT) Mdl type :MDL_EXCLUSIVE(X)
2017-08-03T19:46:54.804306Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T19:46:54.804319Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY
2017-08-03T19:46:54.855563Z3[Note] (downgrade_lock)THIS MDL LOCK will downgrade
2017-08-03T19:46:54.855693Z3[Note] (downgrade_lock) to this MDL lock
2017-08-03T19:46:54.855706Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T19:46:54.855717Z3[Note] (->MDL PRINT) DB_name is:test
2017-08-03T19:46:54.856053Z3[Note] (-->MDL PRINT) OBJ_name is:testsort12
2017-08-03T19:46:54.856069Z3[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T19:46:54.856082Z3[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_UPGRADABLE(SU)
2017-08-03T19:46:54.856094Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T19:46:54.856214Z3[Note] (------->MDL PRIN

我们需要简单分析一下,获得 testsort12 表上的 MDL Lock 大概流程如下:

2017-08-03T19:46:54.781487获得 MDL_SHARED_UPGRADABLE(SU)
2017-08-03T19:46:54.804293升级 MDL_EXCLUSIVE(X) 准备阶段
2017-08-03T19:46:54.855563降级 MDL_SHARED_UPGRADABLE(SU) 执行阶段
2017-08-03T19:47:00.304057升级 MDL_EXCLUSIVE(X) 提交阶段

不管如何这个 ALTER 操作还是比较费时的,从时间我们看到 2017-08-03T19:46:54 降级完成 (SU) 到 2017-08-03T19:47:00 这段时间,实际上是最耗时的实际上这里就是实际的 Inplace 重建,但是这个过程实际在 MDL SU 模式下所以不会堵塞 DML/SELECT 操作。

这里再给大家提个醒,所谓的 ONLINE DDL 只是在 Inplace 重建阶段不堵塞 DML/SELECT 操作,还是尽量在数据库压力小的时候操作,如果有 DML 没有提交或者 SELECT 没有做完这个时候 SW 或者 SR 必然堵塞 X,而 X 为高优先级能够堵塞所有操作。这样导致的现象就是由于 DML 未提交会堵塞 DDL 操作,而 DDL 操作会堵塞所有操作,基本对于这个 TABLE 的表全部操作堵塞(SW 堵塞 X,X 堵塞所有操作)。而对于 ALGORITHM=COPY 在COPY 阶段用的是 SNW 锁,接下来我就先来看看 SNW 锁。

8、MDL_SHARED_NO_WRITE(SNW)

SU 可以升级为 SNW,而 SNW 可以升级为 X,如前面所提及的用于 ALGORITHM=COPY 中,保护数据的一致性。先看看它的兼容性如下:

从兼容矩阵可以看到,本锁不会堵塞 SR,但是堵塞 SW,当然也就堵塞了 DML(SW) 而 SELECT(SR) 不会堵塞。

下面是部分操作记录日志:

MySQL> alter table testsort12 add column ik intnotnull, ALGORITHM=COPY ;

2017-08-03T20:07:58.413215Z3[Note] (upgrade_shared_lock)THIS MDL LOCK upgrade TO
2017-08-03T20:07:58.413241Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T20:07:58.413257Z3[Note] (->MDL PRINT) DB_name is:test
2017-08-03T20:07:58.413273Z3[Note] (-->MDL PRINT) OBJ_name is:testsort12
2017-08-03T20:07:58.413292Z3[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T20:07:58.413308Z3[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_NO_WRITE(SNW)
2017-08-03T20:07:58.413325Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T20:07:58.413341Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY
2017-08-03T20:08:25.392006Z3[Note] (upgrade_shared_lock)THIS MDL LOCK upgrade TO
2017-08-03T20:08:25.392024Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T20:08:25.392086Z3[Note] (->MDL PRINT) DB_name is:test
2017-08-03T20:08:25.392159Z3[Note] (-->MDL PRINT) OBJ_name is:testsort12
2017-08-03T20:08:25.392199Z3[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T20:08:25.392214Z3[Note] (----->MDL PRINT) Mdl type is:MDL_EXCLUSIVE(X)
2017-08-03T20:08:25.392228Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T20:08:25.392242Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY

我们可以发现如下:

2017-08-03T20:07:58.413308获得了MDL_SHARED_NO_WRITE(SNW)
2017-08-03T20:08:25.392006升级为MDL_EXCLUSIVE(X)

2017-08-03T20:07:58.413308 到 2017-08-03T20:08:25.392006 就是实际 COPY 的时间,可见整个 COPY 期间只能 SELECT,而不能 DML。也是 ALGORITHM=COPY 和 ALGORITHM=INPLACE 的一个关键区别。

9、MDL_SHARED_READ_ONLY(SRO)

用于 LOCK TABLES READ  语句,兼容性如下:

根据兼容性可以发现,堵塞 DML(SW) 但是 SELECT(SR) 还是可以的。下面是操作日志:

MySQL> lock table testsort12 read;
Query OK, 0 rows affected (0.01 sec)
2017-08-03T21:08:27.267947Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-03T21:08:27.267979Z3[Note] (>MDL PRINT) Thread id is3:
2017-08-03T21:08:27.268009Z3[Note] (->MDL PRINT) DB_name is:test
2017-08-03T21:08:27.268040Z3[Note] (-->MDL PRINT) OBJ_name is:testsort12
2017-08-03T21:08:27.268070Z3[Note] (--->MDL PRINT) Namespaceis:TABLE
2017-08-03T21:08:27.268113Z3[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ_ONLY(SRO)
2017-08-03T21:08:27.268145Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
2017-08-03T21:08:27.268175Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY

10、MDL_SHARED_NO_READ_WRITE(SNRW)

用于 LOCK TABLES WRITE 语句,兼容性如下:

可以看到 DML(SW) 和 SELECT(SR) 都被它堵塞,但是还可以 DESC(SH)。

操作日志记录如下:

1.  `MySQL> lock table testsort12 write;
2. `Query OK, 0 rows affected (0.00 sec)
3. `2017-08-03T21:13:07.113347Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
4. `2017-08-03T21:13:07.113407Z3[Note] (>MDL PRINT) Thread id is3:
5. `2017-08-03T21:13:07.113435Z3[Note] (--->MDL PRINT) Namespaceis:GLOBAL
6. `2017-08-03T21:13:07.113458Z3[Note] (---->MDL PRINT) Fast path is:(Y)
7. `2017-08-03T21:13:07.113482Z3[Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX)
8. `2017-08-03T21:13:07.113505Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_STATEMENT
9. `2017-08-03T21:13:07.113604Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY
10. `2017-08-03T21:13:07.113637Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
11. `2017-08-03T21:13:07.113660Z3[Note] (>MDL PRINT) Thread id is3:
12. `2017-08-03T21:13:07.113681Z3[Note] (->MDL PRINT) DB_name is:test
13. `2017-08-03T21:13:07.113703Z3[Note] (-->MDL PRINT) OBJ_name is:
14. `2017-08-03T21:13:07.113725Z3[Note] (--->MDL PRINT) Namespaceis:SCHEMA
15. `2017-08-03T21:13:07.113746Z3[Note] (---->MDL PRINT) Fast path is:(Y)
16. `2017-08-03T21:13:07.113768Z3[Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX)
17. `2017-08-03T21:13:07.113791Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
18. `2017-08-03T21:13:07.113813Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY
19. `2017-08-03T21:13:07.113842Z3[Note] (acquire_lock)THIS MDL LOCK acquire ok!
20. `2017-08-03T21:13:07.113865Z3[Note] (>MDL PRINT) Thread id is3:
21. `2017-08-03T21:13:07.113887Z3[Note] (->MDL PRINT) DB_name is:test
22. `2017-08-03T21:13:07.113922Z3[Note] (-->MDL PRINT) OBJ_name is:testsort12
23. `2017-08-03T21:13:07.113945Z3[Note] (--->MDL PRINT) Namespaceis:TABLE
24. `2017-08-03T21:13:07.113975Z3[Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_NO_READ_WRITE(SNRW)
25. `2017-08-03T21:13:07.113998Z3[Note] (------>MDL PRINT) Mdl duration is:MDL_TRANSACTION
26. `2017-08-03T21:13:07.114021Z3[Note] (------->MDL PRINT) Mdl status is:EMPTY

除此之外可以发现语句还需要 GLOBAL 和 SCHEMA 上的 IX 锁,换句话说 flush tables with read lock; 会堵塞‘lock table testsort12 write’,但是‘lock table testsort12 read’却不会堵塞。

11、MDL_EXCLUSIVE(X)

用于各种 DDL 操作,实际上基本全部的 DDL 都会涉及到这个锁,即便是 ONLINE DDL 也会在准备和提交阶段获取本锁,因此 ONLINE DDL 不是完全不堵塞的,只是堵塞时间很短很短,兼容性如下:

我们在验证 SU 和 SNW MDL Lock 类型的时候已经看到了操作记录,不做补充了。

==================================================================================================================================================================================

InnoDB Lock概念和分类

1.共享锁(S)和排他锁(X)

   这两个锁是行级别的锁

  • 共享锁允许事务持有该锁去读取行
  • 排它锁允许事务持有该锁去update和delete行

2.意向锁(IS、IX)

InnoDB支持多粒度锁,允许行锁和表锁共存,这两个锁是表级别的锁;而它们的作用是避免去检查每一行是否持有(行级别的)排他/共享锁。

  • 意向共享锁指明一个事务准备对单行设置共享锁
  • 意向排他锁指明一个事务准备对单行设置排他锁
  X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible

 注意:意向锁不会与行级别的共享/排他锁互斥,上边的兼容图表X/S代表的是表级别的排他/共享锁

3.记录锁

一个记录锁是锁在索引记录行的。(包括主键和二级索引)

 4.gap锁

间隙锁,主要锁住间隙

5.next-key

它是gap锁和record锁的联合,一个表包含10, 11, 13, and 20值,则锁住范围

(negative infinity, 10] (10, 11] (11, 13] (13, 20] (20, positive infinity)
  • 原则1:加锁的基本单位是next-key lock。希望你还记得,next-key lock是前开后闭区间。
  • 原则2:查找过程中访问到的对象才会加锁。
  • 优化1:索引上的等值查询,给唯一索引加锁的时候,next-key lock退化为行锁。
  • 优化2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock退化为间隙锁。
  • 一个bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

举例:select*  from tt where code =6 ,锁住区间(3,6],(6,7),最后7不满足等值条件,退化成间隙锁。

引用:https://segmentfault.com/a/1190000022366564

MySQL的MDL锁的更多相关文章

  1. 有了MDL锁视图,业务死锁从此一目了然

    摘要:MDL锁视图让一线运维人员清晰地查看数据库各session持有和等待的元数据锁信息,从而找出数据库MDL锁等待的根因,准确地进行下一步决策. 当多用户共同存取数据时,数据库中就会产生多个事务同时 ...

  2. 深入理解MYSQL的MDL元数据锁

    1 前言 2 MDL锁与实现 3 MDL锁的性能与并发改进 4 MDL锁的诊断 前言 好久没更新,主要是因为Inside君最近沉迷于一部动画片——<新葫芦娃兄弟>.终于抽得闲,完成了本篇关 ...

  3. MySQL锁系列3 MDL锁

    http://www.cnblogs.com/xpchild/p/3790139.html   MySQL为了保护数据字典元数据,使用了metadata lock,即MDL锁,保证在并发的情况下,结构 ...

  4. mysql 原理 ~ DDL之mdl锁

    一 简介: MDL锁 二 具体 1 MDL锁   1 增删查改 申请MDL读锁   2 ddl语句       1. 拿MDL写锁      2. 降级成MDL读锁      3. 真正做DDL    ...

  5. MySQL里面的锁

    MySQL里面的锁可以分为:全局锁,表级锁,行级锁. 一.全局锁:对整个数据库实例加锁.MySQL提供加全局读锁的方法:Flush tables with read lock(FTWRL)这个命令可以 ...

  6. MySQL实战 | 06/07 简单说说MySQL中的锁

    原文链接:MySQL实战 | 06/07 简单说说MySQL中的锁 本文思维导图:https://mubu.com/doc/AOa-5t-IsG 锁是计算机协调多个进程或纯线程并发访问某一资源的机制. ...

  7. 你了解MySQL中的锁吗?

    MySQL中的锁,分为全局锁.表级锁.行锁 全局锁 全局锁的意思就是,对整个数据库实例加锁,它的命令是FTWRL Flash tables with read lock 这个命令的语义是,使整个库处于 ...

  8. 关于MySQL中的锁机制详解

    锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则. 最显著的特点是不同的存储引擎支持不同的锁机制,InnoDB支持行锁和表锁,MyISAM支持表锁. 表锁就是把 ...

  9. mysql(3):锁和事务

    MySQL锁的介绍 锁是数据库系统区别于文件系统的一个关键特性.锁机制用于管理对共享资源的并发访问. 表级锁 例如MyISAM引擎,其锁是表锁设计.并发情况下的读没有问题,但是并发插入时的性能要差一些 ...

  10. 面试官:MySQL 有哪些锁??

    大家好,我是小林. 这次,来说说 MySQL 的锁,主要是 Q&A 的形式,看起来会比较轻松. 不多 BB 了,发车! 在 MySQL 里,根据加锁的范围,可以分为全局锁.表级锁和行锁三类. ...

随机推荐

  1. windows下解决getAddressInfo Failed的一种办法

    从九点到现在,解决完这个问题就四点了,其实不难,只是第一次遇到和我太菜. 就是管理员身份打开命令行然后输入ipconfig /flushdns,作用是刷新dns解析缓存,这还不够,如果只做这一步,重启 ...

  2. Linux,Lnmp配置Index of /索引页

    其实很简单就是修改conf配置文件 进入域名对应的vhost修改conf文件: 第一种方法 cd /usr/local/nginx/vhost/ 在清楚当前域名所对用的conf文件可以试用 ll 列出 ...

  3. 均值、中值、高斯、non-local means算法详解

    文章仅为个人理解,如有不妥之处欢迎指正. 写几个常见的图像去噪滤波器. 1.均值滤波器 均值滤波器是最简单的图像平滑滤波器,其3*3的模板为 1 9 [ 1 1 1 1 1 1 1 1 1 ] \fr ...

  4. MYSQL 5.7及以上【ONLY_FULL_GROUP_BY】报错和解决方法

    由于同事安装的Docker,就在docker上举例子吧,和非docker的操作方式都一样,只是路径上和重启方式可能不同 1,进入容器 docker exec -it xxxx(你的mysql容器名称) ...

  5. 思科数据中心CCIE稳定PASS

    乾颐堂DC数据中心CCIE,在增加新题的情况下一次PASS! 目前笔试.lab都在过人,需要备考的同学联系乾颐堂,机时充足!

  6. mysql(insert + group by + on duplicate key update)

    group by 的内容设为子表tmp, 外面嵌套一层查询   连接 on duplicate key update key = tmp.new_key

  7. FSL--fsleyes建立软连接方法

    在使用conda下载完fsleyes后,还是显示not found ,无法使用怎么办? 1.首先在/anaconda/envs/fslpython/bin/  中搜索 fsleyes  确定已经下载好 ...

  8. Java中创建线程的方式和线程中常用方法?

    Java中如何创建线程? 继承Thread类 实现Rnnable接口 实现Callable接口 通过线程池创建线程 线程中常用方法 线程等待:wait() 进入等待状态,只有等其他线程唤醒或中断才能运 ...

  9. Spark 中三种数据处理对象的区别: RDD-Dataset-Dataframe

    1,对比表:   RDD Dataframe Dataset 版本 1.0 1.3 1.6 描述 分布式数据集合 行列化的分布式数据集合  RDD 和 DataFrame的结合 数据格式 结构化和非结 ...

  10. Docker CLI docker attach 常用命令

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化.Docker是内核 ...