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

6
我有一堆连接在事务中执行SELECT,还有一个连接执行DDL。mysql手册对于事务中metadata锁的获取非常清晰:
为了确保事务的串行化,服务器不能允许一个会话在另一个未完成的显式或隐式启动的事务中使用的表上执行数据定义语言(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;

在我的系统上,当连接A提交时,连接C执行,而连接B仍然挂起:因为SELECT事务导致其无法执行。我本以为元数据锁等待队列会按照FIFO的顺序进行处理,但似乎并非如此。
关于元数据等待队列处理顺序是否有文件记录?

MySQL的哪个版本? - Rick James
在Debian系统上的5.6.40版本 - mathieu
1个回答

1

关于具体情况:

尝试重现该情况时,我发现会导致会话B被阻塞,然后会话C也被阻塞......请注意,如果会话B在获取表上的元数据锁之前实际上正在等待其他事物,那么会话C就没有理由等待。

现在,总的来说:

已授予的元数据锁可以在performance_schema中的metadata_locks表中看到,其LOCK_STATUSGRANTED

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

这对于查看哪个会话拥有哪个锁非常有帮助。

会话正在等待的元数据锁也可以在同一张表中看到,其LOCK_STATUSPENDING

这对于查看会话正在等待什么非常有帮助。

一个(阻塞的)会话在等待某个东西的锁,而这个东西可能已经被其他会话用各种LOCK_TYPELOCK_DURATION锁住了,但是这里没有直接的“会话X等待会话Y”的关系,它是由已经存在的锁隐含表示的。
当几个会话都在等待同一资源时,当资源可用(一个会话释放了元数据锁)时,试图预测处理顺序是有风险的,应用程序逻辑不应该依赖于此:据我所知,当前实现确实是FIFO,但这可能随时改变,而且没有记录。
这里的理性是服务器必须有一定的自由度,以便实现不同的调度策略,例如出于性能原因。如果某些应用程序“期望”给定的顺序,它将会中断并防止任何更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接