The data_locks
表显示数据锁的持有和请求。该表的行具有 THREAD_ID
列,指示拥有锁的会话的线程 ID,以及 EVENT_ID
列,指示导致锁的性能模式事件。 tuples of (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