手机摄影网站,微商城是怎么做的,wordpress打字不显示,wordpress页面文章列表元数据是用来描述数据对象定义的#xff0c;而元数据锁#xff08;Metadata Lock MDL#xff09;即是加在这些定义上。通常我们认为非锁定一致性读#xff08;简单select#xff09;是不加锁的#xff0c;这个是基于表内数据层面#xff0c;其依然会对表的元…元数据是用来描述数据对象定义的而元数据锁Metadata Lock MDL即是加在这些定义上。通常我们认为非锁定一致性读简单select是不加锁的这个是基于表内数据层面其依然会对表的元数据加锁保证读取数据期间表结构不会变更。
一、元数据锁简介
在事务执行过程中MySQL会对所有涉及对象的定义加上元数据锁语句执行的时候加锁目的是保证事务执行过程中对象定义不被修改你不能在别人查询的时候修改表结构或者把表删了。
对表进行DML操作时select, update等MySQL会对表的定义施加一个共享元数据锁S MDL而进行DDL操作时会施加排他元数据锁X MDL。DML之间的元数据锁时不会互相阻塞的而普通用户通常只会执行DML他们是感知不到元数据锁的。
如果DBA在业务运行期间执行了DDL那么DDL也会尝试获取元数据锁在事务都很短小的时候可能很快就获取到了。但如果有长事务阻塞了DDL那么就有可能导致严重的问题。
示例在会话1中执行下面SQL:
create table t1 (id int primary key auto_increment);
begin;
select * from t1;MySQL对DML默认是自动提交的因此每条DML语句都是独立事务当语句执行完元数据锁就释放了这里通过begin显式开启事务让select语句执行完后事务依然存在。
另启动一个会话2执行下面DDL语句可以发现其被阻塞会话迟迟不返回
alter table t1 add name varchar(16);DDL在执行前会隐式提交事务并释放元数据锁这就是为什么要另一个会话发起DDL。
启动会话3执行show processlist;命令即可看到会话2在等待元数据锁Waiting for table metadata lock
show processlist;二、查看元数据锁
除了表元数据锁也会加在表空间存储过程函数触发器等对象上。但最常遇到的问题是我们想修改表结构但是却被元数据锁阻塞了导致DDL无法执行进一步导致后续DML无法执行业务停滞此时需要进行人工干预。
2.1 查询元数据锁
MySQL提供了performance_schema.metadata_locks用来查询具体元数据锁信息且默认就打开了元数据锁的信息收集直接查询即可。表中包含了持有等待及其他中间状态的MDL数据当锁释放时会从表中删除。
如果没有打开元数据锁信息收集可以执行下面的SQL
update performance_schema.setup_instruments
set enabled YES, timed YES
where name wait/lock/metadata/sql/mdl;也可以持久化写入配置文件需要重启
[mysqld]
performance-schema-instrumentwait/lock/metadata/sql/mdlON我们依然用第1章的示例在执行完会话1的SQL后另开一个会话执行下面SQL
select
l.object_schema 数据库名,
l.object_type 对象类型,
l.object_name 对象名称,
l.lock_type 锁类型,
l.lock_duration 持续类型,
l.lock_status 锁状态,
l.owner_thread_id 线程ID,
t.processlist_id 会话ID,
s.sql_text
from performance_schema.metadata_locks l
join performance_schema.threads t on t.thread_idl.owner_thread_id
join performance_schema.events_statements_current s on s.thread_idl.owner_thread_id
where l.object_schematestand l.object_namet1;锁状态为granted代表成功获取了元数据锁
随后执行会话2的DDL再次执行查询SQL可以看到锁状态pending等待中
通过会话ID锁状态和SQL_Text三个字段可以判断会话ID为4107的select语句阻塞了alter table
2.2 常见问题
元数据锁的获取是有优先级的X锁的优先级要高于S锁。在实际生产环境中如果一个长事务阻塞了DDL由于其尝试获取的是X锁优先级高那么它还会阻止后续DML获取S锁。即DML DDL阻塞 DML阻塞从现象上看就是表无法执行任何操作。
在上面示例的基础上再重新开几个会话执行下面的SQL你会发现所有类型DML都无法返回甚至无法读
insert into t1 values(1,Vincent);
update t1 set nameVictor where id1;
delete from t1 where id1;
select * from t1;如果生产环境出现了DDL阻塞你的processlist可能就是下面的样子堆积的DML会越来越多最后挤爆线程
show procelist;解决方案
尽量避免在业务活跃期间执行DDL特别是有长事务的时候如果已经产生了阻塞立刻取消DDL或将其会话kill掉先让业务运行下去
注Online DDL在运行过程中也会短暂地获取X锁所以并不能解决DDL阻塞问题。