什么是Mysql表元数据锁等待队列排序

mat*_*ieu 6 mysql locking transactions

我有一堆连接在事务中执行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;
Run Code Online (Sandbox Code Playgroud)

在我的系统上,当connectionA提交时,connectionC执行并且connectionB仍然挂起:它缺乏基于SELECT的转换执行.我期待元数据锁等待列表大致按FIFO顺序处理,但似乎并非如此.

是否有关于处理元数据等待队列的顺序的文档?

Mar*_*lff 1

对于该场景的具体情况:

尝试重现该情况,我的会话 B 被阻止,然后会话 C 被阻止...请注意,如果会话 B 在获取表上的元数据锁之前实际上正在等待其他内容,则会话 C 没有理由等待。

现在,一般来说:

performance_schema已授予的元数据锁在表中可见metadata_locks,带有LOCK_STATUSas GRANTED

请参阅文档: https ://dev.mysql.com/doc/refman/8.0/en/metadata-locks-table.html

这有助于查看哪个会话拥有哪个锁。

会话正在等待的元数据锁在同一个表中也可见,带有LOCK_STATUSas PENDING

这有助于查看会话正在等待什么。

(被阻止的)会话等待某个对象的锁定,而该对象可能已经被其他会话锁定(使用各种LOCK_TYPELOCK_DURATION),但这里没有直接的“会话 X 等待会话 Y”关系,这是由锁定隐含的已经就位了。

当多个会话都等待相同的资源,并且当资源可用时(会话释放元数据锁),尝试预测处理顺序(在我看来)是有风险的,应用程序逻辑不应依赖于此:据我所知,当前的实现确实是一个 FIFO,但这可能随时改变,并且没有记录。

这里的合理性是服务器必须具有一定程度的自由度,以便实现不同的调度策略(例如出于性能原因)是可行的。如果某个应用程序以某种方式“期望”给定的顺序,它将中断并阻止任何更改。