标签:
3. 导致 Metadata lock wait 等待的活动事务
5. 如何避免出现长时间 Metadata lock wait 导致表上相关查询阻塞,影响业务
创建、删除索引
修改表结构
表维护操作(optimize table、repair table 等)
删除表
注:
为了在并发环境下维护表元数据的数据一致性,在表上有活动事务(显式或隐式)的时候,不可以对元数据进行写入操作。因此 MySQL 引入了 metadata lock ,来保护表的元数据信息。
因此在对表进行上述操作时,如果表上有活动事务(未提交或回滚),请求写入的会话会等待在 Metadata lock wait 。
当前有对表的长时间查询
显示或者隐式开启事务后未提交或回滚,比如查询完成后未提交或者回滚。
表上有失败的查询事务
show processlist 查看会话有长时间未完成的查询,使用kill 命令终止该查询。
查询 information_schema.innodb_trx 看到有长时间未完成的事务, 使用 kill 命令终止该查询。
select concat(‘kill ‘,i.trx_mysql_thread_id,‘;‘) from information_schema.innodb_trx i,
(select
id, time
from
information_schema.processlist
where
time = (select
max(time)
from
information_schema.processlist
where
state = ‘Waiting for table metadata lock‘
and substring(info, 1, 5) in (‘alter‘ , ‘optim‘, ‘repai‘, ‘lock ‘, ‘drop ‘, ‘creat‘))) p
where timestampdiff(second, i.trx_started, now()) > p.time
and i.trx_mysql_thread_id not in (connection_id(),p.id);
-- 请根据具体的情景修改查询语句
-- 如果导致阻塞的语句的用户与当前用户不同,请使用导致阻塞的语句的用户登录来终止会话
注:关于清理会话,请参考:RDS MySQL 如何终止会话
如果上面两个检查没有发现,或者事务过多,建议使用下面的查询将相关库上的会话终止
-- RDS for MySQL 5.6
select
concat(‘kill ‘, a.owner_thread_id, ‘;‘)
from
information_schema.metadata_locks a
left join
(select
b.owner_thread_id
from
information_schema.metadata_locks b, information_schema.metadata_locks c
where
b.owner_thread_id = c.owner_thread_id
and b.lock_status = ‘granted‘
and c.lock_status = ‘pending‘) d ON a.owner_thread_id = d.owner_thread_id
where
a.lock_status = ‘granted‘
and d.owner_thread_id is null;
-- RDS for MySQL 5.5
select
concat(‘kill ‘, p1.id, ‘;‘)
from
information_schema.processlist p1,
(select
id, time
from
information_schema.processlist
where
time = (select
max(time)
from
information_schema.processlist
where
state = ‘Waiting for table metadata lock‘
and substring(info, 1, 5) in (‘alter‘ , ‘optim‘, ‘repai‘, ‘lock ‘, ‘drop ‘, ‘creat‘, ‘trunc‘))) p2
where
p1.time >= p2.time
and p1.command in (‘Sleep‘ , ‘Query‘)
and p1.id not in (connection_id() , p2.id);
-- RDS for MySQL 5.5 语句请根据具体的 DDL 语句情况修改查询的条件;
-- 如果导致阻塞的语句的用户与当前用户不同,请使用导致阻塞的语句的用户登录来终止会话
在业务低峰期执行上述操作,比如创建删除索引。
在到RDS的数据库连接建立后,设置会话变量 autocommit 为 1 或者 on,比如 set autocommit=1; 或 set autocommit=on; 。
考虑使用事件来终止长时间运行的事务,比如下面的例子中会终止执行时间超过60分钟的事务。
create event my_long_running_trx_monitor
on schedule every 60 minute
starts ‘2015-09-15 11:00:00‘
on completion preserve enable do
begin
declare v_sql varchar(500);
declare no_more_long_running_trx integer default 0;
declare c_tid cursor for
select concat (‘kill ‘,trx_mysql_thread_id,‘;‘)
from information_schema.innodb_trx
where timestampdiff(minute,trx_started,now()) >= 60;
declare continue handler for not found
set no_more_long_running_trx=1;
open c_tid;
repeat
fetch c_tid into v_sql;
set @v_sql=v_sql;
prepare stmt from @v_sql;
execute stmt;
deallocate prepare stmt;
until no_more_long_running_trx end repeat;
close c_tid;
end;
注:请根据您自身情况,自行修改运行间隔和事务执行时长。
执行上述1中操作前,设置会话变量 lock_wait_timeout 为较小值,比如 set lock_wait_timeout=30; 命令可以设置 metadata lock wait 的最长时间为 30 秒;避免长时间等待元数据锁影响表上其他业务查询。
RDS MySQL 表上 Metadata lock 的产生和处理
标签:
原文地址:http://www.cnblogs.com/erisen/p/5967291.html