该 data_locks
表显示已持有的数据锁和请求的数据锁。此表的行有一个 THREAD_ID
列,指示拥有锁的会话的线程 ID,以及一个 EVENT_ID
列,指示导致锁定的性能模式事件。 (THREAD_ID
, EVENT_ID
) 值的元组隐式地标识了其他性能模式表中的父事件。
该
events_waits_
表中的父等待事件xxx
该
events_stages_
表中的父阶段事件xxx
该
events_statements_
表中的父语句事件xxx
该
events_transactions_current
表中的父事务事件
要获取有关父事件的详细信息,请将 THREAD_ID
和 EVENT_ID
列与相应父事件表中同名的列联接。该关系基于嵌套集数据模型,因此联接包含多个子句。假设分别由 parent
和 child
表示的父表和子表,则联接如下所示
WHERE
parent.THREAD_ID = child.THREAD_ID /* 1 */
AND parent.EVENT_ID < child.EVENT_ID /* 2 */
AND (
child.EVENT_ID <= parent.END_EVENT_ID /* 3a */
OR parent.END_EVENT_ID IS NULL /* 3b */
)
联接的条件是
父事件和子事件位于同一线程中。
子事件在父事件之后开始,因此其
EVENT_ID
值大于父事件的值。父事件已完成或仍在运行。
要查找锁定信息,data_locks
是包含子事件的表。
该 data_locks
表仅显示现有锁,因此关于哪个表包含父事件,以下注意事项适用
对于事务,唯一的选择是
events_transactions_current
。如果事务已完成,它可能在事务历史表中,但锁已消失。对于语句,这完全取决于获取锁的语句是已完成事务中的语句(使用
events_statements_history
)还是正在运行的语句(使用events_statements_current
)。对于阶段,逻辑与语句类似;使用
events_stages_history
或events_stages_current
。对于等待,逻辑与语句类似;使用
events_waits_history
或events_waits_current
。但是,记录的等待次数很多,因此导致锁定的等待很可能已从历史表中消失。
等待、阶段和语句事件会很快从历史记录中消失。如果很久以前执行的语句获取了锁,但仍处于打开的事务中,则可能无法找到该语句,但可以找到该事务。
这就是为什么嵌套集数据模型更适合定位父事件的原因。在父/子关系(数据锁 -> 父等待 -> 父阶段 -> 父事务)中遵循链接在中间节点已从历史表中消失时效果不佳。
以下场景说明了如何查找获取锁的语句的父事务
会话 A
[1] START TRANSACTION;
[2] SELECT * FROM t1 WHERE pk = 1;
[3] SELECT 'Hello, world';
会话 B
SELECT ...
FROM performance_schema.events_transactions_current AS parent
INNER JOIN performance_schema.data_locks AS child
WHERE
parent.THREAD_ID = child.THREAD_ID
AND parent.EVENT_ID < child.EVENT_ID
AND (
child.EVENT_ID <= parent.END_EVENT_ID
OR parent.END_EVENT_ID IS NULL
);
对于会话 B 的查询应该显示语句 [2] 拥有对记录 pk=1
的数据锁。
如果会话 A 执行更多语句,[2] 将从历史表中消失。
无论执行了多少语句、阶段或等待,查询都应该显示在 [1] 中开始的事务。
要查看更多数据,还可以使用 events_
表,除了事务,假设服务器中没有其他查询运行(这样可以保留历史记录)。xxx
_history_long