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

标签 mysql transactions locking

我有一堆连接在一个事务中执行 SELECT,一个执行 DDL。 mysql 手册非常清楚如何在事务中获取元数据锁:

To ensure transaction serializability, the server must not permit one session to perform a data definition language (DDL) statement on a table that is used in an uncompleted explicitly or implicitly started transaction in another session. The server achieves this by acquiring metadata locks on tables used within a transaction and deferring release of those locks until the transaction ends. A metadata lock on a table prevents changes to the table's structure. This locking approach has the implication that a table that is being used by a transaction within one session cannot be used in DDL statements by other sessions until the transaction ends.

这是有道理的,我做了这个测试:

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 仍然挂起:它因基于 SELECT 的事务而无法执行。我期待元数据锁定等待列表大致按 FIFO 顺序处理,但似乎并非如此。

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

最佳答案

关于场景的细节:

试图重现这个案例,我阻塞了 session B,然后阻塞了 session C ... 请注意,如果 session B 实际上在获取表上的元数据锁之前正在等待其他内容,则 session C 没有理由等待。

现在,一般来说:

已授予的元数据锁在 performance_schemametadata_locks 中可见,LOCK_STATUSGRANTED .

查看文档: https://dev.mysql.com/doc/refman/8.0/en/metadata-locks-table.html

这有助于查看哪个 session 拥有哪个锁。

session 正在等待的元数据锁在同一个表中也是可见的,LOCK_STATUSPENDING

这有助于了解 session 正在等待什么

一个(阻塞的) session 等待某个东西的锁定,这反过来可能已经被其他 session 锁定(使用各种 LOCK_TYPELOCK_DURATION),但是有这里没有直接的“ session X 等待 session Y”关系,这是由已经存在的锁暗示的。

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

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

关于mysql - 什么是 Mysql 表元数据锁等待队列排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50714253/

相关文章:

mysql - 检测数据何时更改

php - 是否可以仅对 MySQL 的临时表授予插入、更新和删除权限?

python - 仅通过B表的插入操作更新A表的字段

sql - 如何在 Postgres 事务中的下一个查询中使用查询结果?

java - 使用 SimpleReadWriteEJBLock 的锁定问题

c++ - 锁定和操作需要很长时间

php - 值之间的差异 = "";且值= NULL;在 PHP 中?

php - 连接表错误未定义属性

MySQL如何正确使用事务?

c# - 从Azure Redis缓存插入或删除值时,是否需要在代码级别进行同步?