共计 997 个字符,预计需要花费 3 分钟才能阅读完成。
1、背景
在咱们零碎中有一张表它的查问概率十分高。最近有个需要,须要对这个表减少一个字段,然而在减少字段的时候发现零碎中有多个业务呈现了超时操作,那么这个是什么起因导致的呢?通过查阅材料发现是数据库的 MDL 锁 + 事务导致 的。
2、什么是 MDL 锁
MDL 锁属于 表级别的元数据锁。表级别锁分为数据锁和元数据锁,通常咱们说的加锁个别指的是加的数据锁。跟数据锁一样,元数据锁也分读锁和读写锁。
MDL 不须要显示应用,在进行表操作时会主动加上。当对表进行增删改查时,会主动加上 MDL 读锁;当要对表进行加减字段的构造批改时,会主动加上 MDL 写锁。
- 读锁不互斥,意味着能够多个线程同时对一张表进行增删改查的操作。
- 写锁独占,进行构造批改前,要先期待其余所有的 MDL 锁开释了能力获取到 MDL 写锁。获取到写锁后,在写锁开释前,其余线程无奈获取到 MDL 读锁和写锁。也就是说,批改一个表的构造过程中,会阻塞其余线程对表的操作。
3、MDL 锁的必要性
MDL 锁的存在,其实是为了保证数据的一致性。设想一下,如果没有 MDL 锁,一个查问在遍历表数据的过程中,另外一个线程执行了 ALTER TABLE t DELETE COLUMN 'col_1'
把col_1
这一列删掉了,那查问后果就乱了,后果中是否应该有这一列数据?
4、举例说明
✅:示意失常往下执行
❌:示意卡住了,即无奈往下执行。
事物一 | 事物二 | 事物三 |
---|---|---|
start transaction;✅ 1️⃣ | ||
select * from customer;✅2️⃣ | alter table customer add column_4 int null;❌3️⃣ | |
select * from customer;❌4️⃣ | ||
commit;✅5️⃣ | ✅6️⃣ | ✅7️⃣ |
解释:
步骤 1️⃣2️⃣失常执行。执行步骤 2️⃣时,会申请表 customer
的MDL 的 SHARED_READ 锁
。
步骤 3️⃣会卡住,因为此时会申请表 customer
的MDL 的 EXCLUSIVE 锁
,然而事物一的事物没有提交,此时是无奈申请到EXCLUSIVE
锁,因为它们是互斥的。
步骤 4️⃣也会卡住,因为 EXCLUSIVE
锁和 SHARE_READ
锁是互斥的,且 EXCLUSIVE
锁的优先级更高,所以步骤 4️⃣也会卡住。
步骤 5️⃣事物提交,开释表的 SHARE_READ
锁,之后就能够执行 6️⃣和 7️⃣的操作了。
如果先执行事务二,在执行事务三,则是能够胜利的,因为 alter 数据 ddl 语句,和事物无关。