RDS MySQL 表上 Metadata lock 的产生和处理

1. Metadata lock wait 出现的场景

2. Metadata lock wait 的含义

3. 导致 Metadata lock wait 等待的活动事务

4. 解决方案

5. 如何避免出现长时间 Metadata lock wait 导致表上相关查询阻塞,影响业务


1. Metadata lock wait 出现的场景

  • 创建、删除索引
  • 修改表结构
  • 表维护操作(optimize table、repair table 等)
  • 删除表
  • 获取表上表级写锁 (lock table tab_name write)

注:

  • 支持事务的 InnoDB 引擎表和 不支持事务的 MyISAM 引擎表,都会出现 Metadata Lock Wait 等待现象。
  • 一旦出现 Metadata Lock Wait 等待现象,后续所有对该表的访问都会阻塞在该等待上,导致连接堆积,业务受影响。

2. Metadata lock wait 的含义

为了在并发环境下维护表元数据的数据一致性,在表上有活动事务(显式或隐式)的时候,不可以对元数据进行写入操作。因此 MySQL 引入了 metadata lock ,来保护表的元数据信息。

因此在对表进行上述操作时,如果表上有活动事务(未提交或回滚),请求写入的会话会等待在 Metadata lock wait 。

3. 导致 Metadata lock wait 等待的活动事务

  • 当前有对表的长时间查询
  • 显示或者隐式开启事务后未提交或回滚,比如查询完成后未提交或者回滚。
  • 表上有失败的查询事务

4. 解决方案

  • 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 语句情况修改查询的条件;
    -- 如果导致阻塞的语句的用户与当前用户不同,请使用导致阻塞的语句的用户登录来终止会话

5. 如何避免出现长时间 metadata lock wait 导致表上相关查询阻塞,影响业务

  • 在业务低峰期执行上述操作,比如创建删除索引。
  • 在到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 秒;避免长时间等待元数据锁影响表上其他业务查询。

时间: 2024-10-07 04:51:09

RDS MySQL 表上 Metadata lock 的产生和处理的相关文章

Mysql事物与Metadata lock 问题

环境说明: MySQL 5.6.16 OS:Linux RedHat 6.2 64bit 1.问题描述 目前新上一个使用MySQL数据库项目,在数据库中,每隔5分钟做truncate某个表操作,经常出现metadata lock锁等待,导致后面的对这个表的所有操作(包括读)全部metadata lock等待.严重影响了数据库运行. 且metadata lock锁等待不同于普通的行级锁,等待超时时间默认为365天,而普通的行级锁超时是120s mysql> show variables like

RDS MySQL 连接数满情况的处理

RDS MySQL 连接数满情况的处理 RDS MySQL 连接数满有2种情况 1. 空闲连接过多 原因: 应用使用长连接模式 - 对于长连接模式(比如Java应用),应用侧应该配置连接池.连接池的初始连接数设置过高,应用启动后建立多个到RDS实例空闲连接.如果出现连接数满(too many connections)不能连接的问题,请检查连接池是否启用了复用连接功能. 应用使用短连接模式 - 对于短连接模式(比如PHP应用),出现大量的空闲连接说明应用没有在查询执行完毕后显式的关闭连接.用户应该

MySQL出现Waiting for table metadata lock的原因以及解决方法

转自:http://ctripmysqldba.iteye.com/blog/1938150 (有修改) MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)都无法进行,因为他们也会在Opening tables的阶段进入到Waiting for

mysql metadata lock锁

很多情况下,很多问题从理论上或者管理上而言都是可以避免或者说很好解决的,但是一旦涉及到现实由于管理或者协调或者规范执行的不够到位,就会出现各种各样本不该出现的问题,这些问题的通常在生产环境并不会出现,但是现实是无论在任何环节出现,都得去找到解决方法,很多时候原因是一部分,预防措施也是一部分,但解决方法也是必须的,因为不可能跟所有的开发人员说你按照我说的做就没有问题了,因为总会有人疏忽了或者忽视了. 前两天,测试环境升级脚本,跑到一半就报锁超时了,好几次后测试让协助而解决下.看了下,是个trunc

mysql metadata lock(二)

上一篇<mysql metadata lock(一)>介绍了为什么引入MDL,MDL作用以及MDL锁导致阻塞的几种典型场景,文章的最后还留下了一个小小的疑问.本文将更详细的介绍MDL,主要侧重介绍MDL的原理和实现.一般而言,商业数据库系统实现锁,一般将锁划分为读锁(共享锁)和写锁(排它锁),为了进一步提高并发性,还会加入意向共享锁和意向排它锁.但是偏偏mysql的MDL搞地比较复杂,但目的也是为了提高并发度.MDL包含有9种类型,详细参考表1.主要其实也是两大类,只是对共享锁做了进一步细分.

关于mysql的metadata lock

昨天晚上上线,却发现一个ddl语句长时间没有生效 查processlist, 发现包括ddl语句在内的众多查询提示 “Waiting for table metadata lock” 唯一没有该提示的查询为一个全表查询,并且Time项数值最大. kill掉这个查询的线程,后面的ddl语句正常进行了 之前一直听说metadata lock,就是元数据锁,也叫字典锁或者表结构锁.但是没有遇到过. 后来又试了一下——只要在session1里有未完成的增删查改事务,如果在另一个session2中出现加表

【MySQL经典案例分析】 Waiting for table metadata lock

本文由云+社区发表 一. 问题是这样来的 ? 2018年某个周末,接到连续数据库的告警,告警信息如下: 二. 苦逼的探索过程 1.总体的思路 看到too many connection的报错信息,基本上可以把问题定位在: (1)机器负载飙升,导致SQL执行效率下降,导致连接推积 (2)业务访问量突增(或者有SQL注入现象),导致连接数打满 (3)出现"死锁"或者锁竞争严重,导致大量SQL堆积 2.排查过程 (1)机器的各项性能指标都显示正常, 没有出现高负载现象,暂时先排除了这种原因

MySQL Waiting for table metadata lock的解决方法

最近需要在某一个表中新增字段,使用Sequel Pro 或者Navicat工具都会出现程序没有反应,使用 show processlist 查看,满屏都是 Waiting for table metadata lock 状态的连接,第一反应当然是 kill 掉这些链接,但是假如太多怎么办?遂在找寻其他办法. 在网上查询得知MySQL在进行一些alter table等DDL操作时,如果该表上有未提交的事务则会出现 Waiting for table metadata lock ,而一旦出现meta

MySQL出现Waiting for table metadata lock的原因以及解决方法(转)

MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)都无法进行,因为他们也会在Opening tables的阶段进入到Waiting for table metadata lock的锁等待队列.如果是产品环境的核心表出现了这样的锁等待队列,就会造成