前言

最近在进行数据库变更(扩展VARCHAR)的时候锁表了,原本以为ONLINE DDL不会锁表,没想到还有很多细节;

MDL

MySQL为了在并发环境下维护表元数据的数据一致性,在表上执行事务(显式或隐式)的时候,不可以对表元数据进行写入操作。因此从MySQL5.5版本开始引入了MDL锁(metadata lock),来保护表的元数据信息,用于解决或者保证DDL操作与DML操作之间的一致性。

MDL (metadata lock) 是表级锁,在访问一个表时会自动被加上:当对一个表做增删改查操作的时候,加MDL读锁;当要对表做结构变更操作的时候,加MDL写锁。

一个事务中的MDL,在语句执行时申请,在事务提交时释放。所以要避免长事务一直占着MDL,如果长事务A加了读锁,然后B是个DDL需要写锁,B就会被A阻塞,再然后所有读锁都会被B阻塞,等于直到A结束前这个表就完全不可读写了。

ONLINE DDL

ONLINE DDL:在进行表变更时,不会堵塞线上业务读写,保障在变更时,库依然能正常对外提供访问。

那就奇怪了,alter这种要加MDL写锁的,咋还能增删改呢,增删改不是要MDL读锁吗,这俩互斥啊。原来为了实现Online DDL,这个MDL在真正拷贝数据之前就退化成读锁了。最耗时的拷贝数据阶段可以接受增删改,真正锁住的时间很短,可以认为是Online的。

ONLINE DDL全过程:

image.png

ONLINE DDL的用法:

alter table . , ALGORITHM [=] { INPLACE | COPY | DEFAULT}, LOCK [=] { DEFAULT | NONE | SHARED | EXCLUSIVE }

并不是所有的DDL都能用INPLACE,具体的支持情况可以在官方文档中查看;要注意版本不同有时会有很大不同,比如扩展VARCHAR长度

为什么会锁表

总之

总之,alter table的语句是很危险的: