一、MDL(Metadata
Lock)
MDL,就是通常所说的表的Metadata
Lock。5.5.3以及5.6版本,对这块的定义越来越清晰。从5.6来讲,MySQL对MDL分为两个维度来管理:时间和粒度。
1.时间(duration)维度
MySQL从对锁持有的时间上来讲,分为三种:statement,transaction和explicit。
·
Statement:从语句开始执行时获取,到语句执行结束时释放。
·
Transaction:在一个事务中,此事务所涉及到的所有表获取MDL,一直到事务commit或者rollback(或:线程中终清理)才释放。
·
Explicit:需要MDL_context::release_lock()显式释放。语句或者事务结束,也仍然持有。如Lock
table, flush .. with lock语句等。
2.粒度(type)
MySQL对锁的粒度的区分,又分为两种:scope锁(MDL_scoped_lock)和object锁(MDL_object_lock)
Scope锁:
分为4种类型,适用于global/schema/commit。
IS:意向范围共享锁,最低级锁,与其它三种都兼容。
IX:意向范围排它锁,与IX兼容,与S,X不兼容。
S: 范围共享锁,与S兼容,与IX,X不兼容。
X: 范围排它锁,与IX,S,X不兼容。
优先级上,X>S>IX。IS与其它三者都兼容,通常我们不太关注。
object锁:
分为9种类型,适用于具体对象如,table/function/procedure/view/event等。
·
MDL_INTENTION_EXCLUSIVE:意向排它锁。仅用于范围锁上,可升级到exclusive。持有者可申请单个对像的排它锁。
·
MDL_SHARED:能读表metadata信息,不可对表数据读写。
·
MDL_SHARED_HIGH_PRIO:与MDL_SHARED相比,在申请时,会忽略正在申请的排它锁。主要用在information_schema信息的填充。
·
MDL_SHARED_READ:能读表metadata信息,也可读表数据。如查询和子查询,Lock table
… read等。
·
MDL_SHARED_WRITE:涉及到DML操作以及select
… update时申请。但DDL和Lock table … write时,不申请此锁。
·
MDL_SHARED_UPGRADABLE:通常在DDL第一阶段获取。可升级到MDL_SHARED_NO_WRITE和
MDL_EXCLUSIVE。
·
MDL_SHARED_NO_WRITE:通常在DDL第一阶段获取。也是一个可升级锁,可升级到MDL_EXCLUSIVE。此锁阻止任何对表的写操作,但允许并发读。通常被用于需要out of
place DDL的第一个阶段。
·
MDL_SHARED_NO_READ_WRITE:也是一个可升级锁,可升级到MDL_EXCLUSIVE。但是阻止对表的读写操作。用于Lock
table … write。
·
MDL_EXCLUSIVE:最高级别MDL锁,通常用于Drop/Create/Rename等操作。也用于其它对象创建或者删除时,如create
trigger等。
锁的兼容矩阵:
这9种类型,大致上是从低到高排序的。另外也是根据对表的metadata信息和表的数据访问结合来确定的。
·
MDL_key类:代表具体的元数据项,由namespace(包含table,view,trigger等)+database
name+table name组成。
·
MDL_request类:代表MDL的请求,以链表结构存储。其中还包含锁的duration,锁的类型(type)等。
·
MDL_ticket类:代表已经获取到的MDL锁。
对于不同的DDL或者DML操作,不同的阶段,所持有锁的等级也不一样,但是都可以归到上面几种类型中去。结合锁的时间维度和粒度,可以产生非常多的有趣现象。