data_locks 表显示了持有和请求的数据锁。该表的行有一个 THREAD_ID 列,表示拥有锁的会话的线程 ID,还有一个 EVENT_ID 列,表示导致该锁的 Performance Schema 事件。(THREAD_ID, EVENT_ID) 值的元组在其他 Performance Schema 表中隐式标识一个父事件:The data_locks table shows data
locks held and requested. Rows of this table have a
THREAD_ID column indicating the thread ID of
the session that owns the lock, and an
EVENT_ID column indicating the Performance
Schema event that caused the lock. Tuples of
(THREAD_ID, EVENT_ID)
values implicitly identify a parent event in other Performance
Schema tables:
events_waits_表中的父等待事件The parent wait event in thexxxevents_waits_tablesxxxevents_stages_表中的父阶段事件The parent stage event in thexxxevents_stages_tablesxxx在
events_statements_表中的父语句事件The parent statement event in thexxxevents_statements_tablesxxx在
events_transactions_current表中的父事务事件The parent transaction event in theevents_transactions_currenttable
要获取有关父事件的详细信息,将 THREAD_ID 和 EVENT_ID 列与相应父事件表中同名列进行连接。该关系基于嵌套集数据模型,因此连接包含多个条件。给定由 parent 和 child 表示的父表和子表,连接如下所示:To obtain details about the parent event, join the
THREAD_ID and EVENT_ID
columns with the columns of like name in the appropriate parent
event table. The relation is based on a nested set data model,
so the join has several clauses. Given parent and child tables
represented by parent and
child, respectively, the join looks like
this:
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 */
)
连接条件为:The conditions for the join are:
父事件和子事件在同一线程中。The parent and child events are in the same thread.
子事件在父事件之后开始,因此其
EVENT_ID值大于父事件的值。The child event begins after the parent event, so itsEVENT_IDvalue is greater than that of the parent.父事件要么已经完成,要么仍在运行中。The parent event has either completed or is still running.
要查找锁信息,data_locks 表包含子事件。To find lock information,
data_locks is the table containing
child events.
data_locks 表仅显示现有锁,因此关于哪个表包含父事件,应考虑以下内容:The data_locks table shows only
existing locks, so these considerations apply regarding which
table contains the parent event:
对于事务,唯一的选择是
events_transactions_current。如果事务已经完成,它可能会出现在事务历史表中,但锁已不存在。For transactions, the only choice isevents_transactions_current. If a transaction is completed, it may be in the transaction history tables, but the locks are gone already.对于语句,这完全取决于获取锁的语句是否属于已经完成的事务(使用
events_statements_history)或语句尚在运行(使用events_statements_current)。For statements, it all depends on whether the statement that took a lock is a statement in a transaction that has already completed (useevents_statements_history) or the statement is still running (useevents_statements_current).对于阶段,其逻辑与语句类似;使用
events_stages_history或events_stages_current。For stages, the logic is similar to that for statements; useevents_stages_historyorevents_stages_current.对于等待,逻辑与语句类似;使用
events_waits_history或events_waits_current。然而,记录的等待事件非常多,导致锁的等待事件很可能已经从历史表中消失。For waits, the logic is similar to that for statements; useevents_waits_historyorevents_waits_current. However, so many waits are recorded that the wait that caused a lock is most likely gone from the history tables already.
等待、阶段和语句事件会很快从历史中消失。如果一个很久之前执行的语句获取了锁但事务仍然未提交,可能无法找到该语句,但可以找到该事务。Wait, stage, and statement events disappear quickly from the history. If a statement that executed a long time ago took a lock but is in a still-open transaction, it might not be possible to find the statement, but it is possible to find the transaction.
这就是为什么嵌套集合数据模型在定位父事件时更有效。当中间节点已经从历史表中消失时,通过父/子关系(数据锁 -> 父等待 -> 父阶段 -> 父事务)进行链接通常行不通。This is why the nested set data model works better for locating parent events. Following links in a parent/child relationship (data lock -> parent wait -> parent stage -> parent transaction) does not work well when intermediate nodes are already gone from the history tables.
下面的场景说明了如何找到一个在其中获取了锁的语句的父事务:The following scenario illustrates how to find the parent transaction of a statement in which a lock was taken:
会话 A:Session A:
[1] START TRANSACTION; [2] SELECT * FROM t1 WHERE pk = 1; [3] SELECT 'Hello, world';
会话 B:Session 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 的记录上的数据锁。The query for session B should show statement [2] as owning a
data lock on the record with pk=1.
如果会话 A 执行更多语句,[2] 会在历史表中消失。If session A executes more statements, [2] fades out of the history table.
查询应显示从 [1] 开始的事务,无论执行了多少语句、阶段或等待。The query should show the transaction that started in [1], regardless of how many statements, stages, or waits were executed.
要查看更多数据,你也可以使用 events_ 表,除了 transactions,前提是假设服务器上没有其他查询运行(以便历史数据得以保留)。To see more data, you can also use the
xxx_history_longevents_
tables, except for transactions, assuming no other query runs in
the server (so that history is preserved).xxx_history_long