我有一堆连接在事务中执行select,还有一个执行ddl。mysql手册非常清楚如何在事务中获取元数据锁:
为确保事务序列化,服务器不得允许一个会话对另一个会话中未完成的显式或隐式启动事务中使用的表执行数据定义语言(ddl)语句。服务器通过获取事务中使用的表上的元数据锁并将这些锁的释放推迟到事务结束来实现这一点。表上的元数据锁可防止更改表的结构。这种锁定方法意味着,在事务结束之前,一个会话中的事务正在使用的表不能被其他会话在ddl语句中使用。
这很有道理,所以我做了这个测试:
connectionA$ begin;
connectionA$ select * from facebook_authorizations;
connectionA$ ....
connectionB$ alter table facebook_authorizations add column foo int default null;
connectionC$ begin;
connectionC$ select * from facebook_authorizations;
connectionA$ commit;
在我的系统上,当connectiona提交时,connectionc执行,而connectionb仍然挂起:它被基于选择的事务剥夺了执行。我原以为元数据锁等待列表将按fifo顺序大致处理,但似乎不是这样。
有关于元数据等待队列处理顺序的文档吗?
1条答案
按热度按时间hmae6n7t1#
有关场景的详细信息:
为了重现这个案子,我先阻止了b组,然后阻止了c组。。。注意,如果会话b实际上在获取表上的元数据锁之前正在等待其他东西,那么会话c没有理由等待。
一般来说:
已授予的元数据锁在中可见
performance_schema
,在表中metadata_locks
,带有LOCK_STATUS
作为GRANTED
.见文件:https://dev.mysql.com/doc/refman/8.0/en/metadata-locks-table.html
这有助于查看哪个会话拥有哪个锁。
会话正在等待的元数据锁也在同一个表中可见,其中
LOCK_STATUS
作为PENDING
.这有助于了解会话正在等待什么。
(被阻止的)会话等待某个对象上的锁,而该对象又可能已经被锁定(使用不同的方法)
LOCK_TYPE
以及LOCK_DURATION
)由其他会话,但这里没有直接的“会话x等待会话y”关系,是由已经就位的锁暗示的。当多个会话都在等待同一个资源时,当资源可用时(会话释放了元数据锁),尝试预测处理顺序(在我看来)是有风险的,应用程序逻辑不应该依赖于此:据我所知,当前的实现确实是一个fifo,但这可能随时改变,而且没有记录在案。
这里的理由是服务器必须有一定的自由度,因此实现不同的调度策略(例如出于性能原因)是可行的。如果某个应用程序以某种方式“期望”给定的顺序,它将中断并阻止任何更改。