阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

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

105次阅读
没有评论

共计 2984 个字符,预计需要花费 8 分钟才能阅读完成。

1. Metadata lock wait 出现的场景

  • 创建、删除索引

  • 修改表结构

  • 表维护操作(optimize table、repair table 等)

  • 删除表

  • 获取表上表级写锁 (lock table tab_name write)

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

注:

  • 支持事务的 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 命令终止该查询。

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

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

  • 查询 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 表上 Metadata lock 的产生和处理

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

注:关于清理会话,请参考:RDS MySQL 如何终止会话  http://www.linuxidc.com/Linux/2016-08/134768.htm

  • 如果上面两个检查没有发现,或者事务过多,建议使用下面的查询将相关库上的会话终止
     

    -- 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 MySQL 表上 Metadata lock 的产生和处理

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 秒;避免长时间等待元数据锁影响表上其他业务查询。

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

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2016-08/134767.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计2984字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中