开发者社区> 问答> 正文

【RDS】MDL锁导致无法操作数据库,该怎么办?

已解决

MDL锁导致无法操作数据库,该怎么办?

展开
收起
云上猫猫 2022-01-14 11:11:30 786 0
1 条回答
写回答
取消 提交回答
  • 采纳回答

    1、通过DMS登录RDS数据库。

    说明:网络地址和端口需要输入对应RDS实例的内网地址及内网端口,可在RDS管理控制台中的RDS实例基本信息页面查看。

    2、在首页上方单击SQL窗口。

    3、在命令行中执行以下SQL语句,查看所有线程状态。

    show full processlist;

    系统显示类似如下,确认在State列存在大量“Waiting for table metadata lock”信息, 即表示出现阻塞。在对应的Info列查看是对哪个表进行的操作,找到正在对该表进行操作的会话,查看并记录对应的会话ID。 image (4).png

    说明:

    a.这里需要找到的是一直在占用该表的会话,而不是正在等待MDL锁解除的会话,注意区分。可以根据State列的状态和Info列的命令内容来进行分析判断。

    b.您也可以执行如下SQL语句,查询长时间未完成的事务。如果导致阻塞语句的用户与当前用户不同,请使用执行SQL语句导致阻塞的用户登录来终止会话。

    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);
    

    4、执行以下SQL语句,结束正在进行的会话解除MDL锁。

    kill [$ID]

    5、后续维护:

    • 在业务低峰期执行相关场景操作,例如创建索引、删除索引等。

    • 开启事务自动提交autocommit。

    • 将lock_wait_timeout参数设置为较小值。

    • 考虑使用事件来终止长时间运行的事务,比如下面的例子中会终止执行时间超过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
    
    2022-01-14 11:17:03
    赞同 展开评论 打赏
来源圈子
更多
收录在圈子:
问答排行榜
最热
最新

相关电子书

更多
2022 DTCC-阿里云一站式数据库上云最佳实践 立即下载
云时代的数据库技术趋势 立即下载
超大型金融机构国产数据库全面迁移成功实践 立即下载