【MySQL】MySQL-锁等待(Waiting for table metadata lock)

【MySQL】MySQL-锁等待(Waiting for table metadata lock)


Waiting for table metadata lock

说明

在使用mysql的时候,我们有时会碰到Waiting for table metadata lock的锁等待。但是这个锁等待比较特殊,在innodb_lock_wait和show engine innodb status 表里面都查不到。

如果一个表产生了Waiting for table metadata lock,那么针对该表的任何操作都会被锁住,包括select,这个影响很大,可以通过配置参数lock_wait_timeout来减少这种锁可以等待的时长,不过最重要的还是减少这种锁等待的产生。

mysql> show variables like 'lock_wait_timeout';
+-------------------+----------+
| Variable_name     | Value    |
+-------------------+----------+
| lock_wait_timeout | 31536000 |
+-------------------+----------+
1 row in set, 1 warning (0.00 sec)

This variables specifies the timeout in seconds for attempts to acquire metadata locks. The permissible values range from 1 to 31536000(1 year). The default is 35536000.

方法1:innodb_trx

select t.PROCESSLIST_ID,
       t.PROCESSLIST_USER,
			 t.PROCESSLIST_HOST,
			 t.PROCESSLIST_DB,
			 t.PROCESSLIST_STATE,
			 t.PROCESSLIST_COMMAND,
			 t.PROCESSLIST_TIME,
			 t.PROCESSLIST_INFO,
			 e.CURRENT_SCHEMA,
			 GROUP_CONCAT(e.SQL_TEXT SEPARATOR ' ') as sqL_text
from performance_schema.threads t,
		 information_schema.INNODB_TRX trx,
		 performance_schema.events_statements_history e
where t.THREAD_ID = e.THREAD_ID
      and t.PROCESSLIST_ID = trx.trx_mysql_thread_id
group by t.THREAD_ID DESC

如果能查询到一个会话,那么肯定就是这个造成的

如果查询结果是多于一个会话,可以通过processlist_info字段里面的SQL来判断出是哪一个。但是有些情况下,持有metadata锁的会话是在sleep状态下的。也就是说造成持有这个锁的语句已经执行过了,但是由于没有提交或者回滚,导致会话还是持有这个锁。如果碰到这种情况,processlist_info字段就可能是空的,那就只能通过判断会话已经执行过的语句来猜了。

MySQL有一个events_statements_history表,可以通过连接这个表来查看会话执行过什么语句。如果有涉及到等待锁的表的语句就能大概猜出是哪一个了。

但是这个events_statements_history有一个限制,他不会存储所有执行过的语句,而是存储最新执行过的N个语句。这个N是由performance_schema_events_statements_history_size控制的,该参数是只读的,只能重启mysql生效,默认是10。如果执行过的语句超过了这个限制,那么很有可能是看不到对这个表进行修改的语句的,这个时候只能靠猜了。

方法2:metadata_locks表

从MySQL5.7开始,有了performance_schema.metadata_locks表,用于显示等待和持有metadata锁的会话信息。有效的简化了处理metadata锁等待的方法。

5.7版本该特性不是默认开启的,需要手动启动。8.0开始是默认开启的,不需要配置。

#5.7的文档

Metadata lock instrumentation uses the wait/lock/metadata/sql/mdl instrument, which is disabled by default.

#8.0的文档

Metadata lock instrumentation uses the wait/lock/metadata/sql/mdl instrument, which is enabled by default.

开启和关闭

-- 查询是否开启
select * from performance_schema.setup_instruments where name = 'wait/lock/metadata/sql/mdl';

-- 在线开启方法
update performance_schema.setup_instruments
set ENABLED	= 'YES',TIMED = 'YES'
where NAME = 'wait/lock/metadata/sql/mdl';

-- 在线关闭方法
update performance_schema.setup_instruments
set ENABLED	= 'NO',TIMED = 'NO'
where NAME = 'wait/lock/metadata/sql/mdl';

-- 永久开启方法
在配置文件的mysqld区块里面添加
performance-schema-instrument='wait/lock/metadata/sql/mdl'

查询sql

select 
       t1.object_schema,
			 t1.object_name,
			 t1.lock_type,
			 t1.lock_status,
			 t2.PROCESSLIST_ID,
       t2.PROCESSLIST_USER,
			 t2.PROCESSLIST_HOST,
			 t2.PROCESSLIST_DB,
			 t2.PROCESSLIST_STATE,
			 t2.PROCESSLIST_COMMAND,
			 t2.PROCESSLIST_TIME,
			 t2.PROCESSLIST_INFO
from performance_schema.metadata_locks t1,
		 performance_schema.threads t2
where t1.owner_thread_id = t2.THREAD_ID
      and t1.object_schema = '数据库名'
			and t1.object_name = '表名';

只有开启特性以后出现的持有或者等待metadata锁的会话才会被记录。

查询结果中lock_status字段,granted表示持有锁,pending表示等待锁

总结

  • MySQL 5.6,使用方法1处理
  • MySQL 5.7,先判断是否开启了metadata_locks表特性,如果开启了使用方法2,否则使用方法1
  • MySQL 8.0,使用方法2
  • 及时提交或者缩短SQL执行时间(优化SQL),可以减少Waiting for table metadata lock出现次数
  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MySQL 8中的“waiting for table metadata lock”错误通常表示在运行某个查询或DML语句时,另一个进程已经占据了需要访问的数据表或索引,导致当前进程无法获取到对应的元数据,从而无法继续执行。 元数据MySQL中的一种排他,用于保护数据表的元数据信息(例如表结构、索引信息等)。当一个进程需要查询或修改数据表的元数据时,它会请求获得对应的元数据,以保证自己能够独占这些元数据信息的访问。但是,如果另一个进程已经占据了相应的,当前进程就需要等待的释放才能继续执行,这就是“waiting for table metadata lock”的错误原因。 为了避免这个问题,我们可以尝试采取以下措施: 1. 使用更高的隔离级别(如repeatable read或serializable)来保证访问数据表时的可重复读性,从而减少对元数据的频繁访问和冲突的机会。 2. 减少对数据表结构的频繁修改操作,避免在高并发环境中进行DDL语句(如ALTER TABLE)的执行。 3. 尽量避免将多个操作合并成一条长SQL语句,尽可能将多个小操作拆分成多条短SQL语句,从而减少对数据表的定时间。 4. 使用更高效的数据库架构设计(如分库分表、索引优化等),将数据的读写操作分配到更多的物理资源中,从而减少对单个数据表的定时间。 在实际进行MySQL数据库开发或运维时,我们需要注意以上几点,以避免“waiting for table metadata lock”错误的发生。如果不幸遇到此类问题,我们需要通过查看进程列表、慢查询日志、错误日志或排查sql执行计划等方式,以找出造成冲突的根本原因。针对不同的错误原因,我们可以采取不同的解决方法,从而有效避免MySQL 8中的元数据问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tzq@2018

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值