本节描述了使用锁定信息,如 Performance Schema data_locks
和 data_lock_waits
表所暴露的锁定信息。
有时,标识哪个事务阻塞了另一个事务非常有帮助。包含 InnoDB 事务和数据锁信息的表使您能够确定哪个事务正在等待另一个事务,并且哪个资源正在被请求。(有关这些表的描述,请参阅 第 17.15.2 节,“InnoDB INFORMATION_SCHEMA 事务和锁定信息”。)
假设三个会话同时运行。每个会话对应一个 MySQL 线程,并执行一个事务接着另一个事务。考虑系统在这些会话执行以下语句但尚未提交事务时的状态:
-
会话 A:
BEGIN; SELECT a FROM t FOR UPDATE; SELECT SLEEP(100);
-
会话 B:
SELECT b FROM t FOR UPDATE;
-
会话 C:
SELECT c FROM t FOR UPDATE;
在这种情况下,使用以下查询来查看哪些事务正在等待和哪些事务正在阻塞它们:
SELECT
r.trx_id waiting_trx_id,
r.trx_mysql_thread_id waiting_thread,
r.trx_query waiting_query,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query
FROM performance_schema.data_lock_waits w
INNER JOIN information_schema.innodb_trx b
ON b.trx_id = w.blocking_engine_transaction_id
INNER JOIN information_schema.innodb_trx r
ON r.trx_id = w.requesting_engine_transaction_id;
或者,更简单地,使用 sys
架构 innodb_lock_waits
视图:
SELECT
waiting_trx_id,
waiting_pid,
waiting_query,
blocking_trx_id,
blocking_pid,
blocking_query
FROM sys.innodb_lock_waits;
如果报告了 NULL 值的阻塞查询,请参阅 标识阻塞查询 After the Issuing Session Becomes Idle。
waiting trx id | waiting thread | waiting query | blocking trx id | blocking thread | blocking query |
---|---|---|---|---|---|
A4 |
6 |
SELECT b FROM t FOR UPDATE |
A3 |
5 |
SELECT SLEEP(100) |
A5 |
7 |
SELECT c FROM t FOR UPDATE |
A3 |
5 |
SELECT SLEEP(100) |
A5 |
7 |
SELECT c FROM t FOR UPDATE |
A4 |
6 |
SELECT b FROM t FOR UPDATE |
在上表中,您可以通过 “等待查询” 或 “阻塞查询” 列来标识会话。正如您所见:
-
会话 B(trx id
A4
,线程6
)和会话 C(trx idA5
,线程7
)都在等待会话 A(trx idA3
,线程5
)。 -
会话 C 也在等待会话 B。
您可以在 INFORMATION_SCHEMA
INNODB_TRX
表和 Performance Schema data_locks
和 data_lock_waits
表中查看基础数据。
以下表显示了 INNODB_TRX
表的一些示例内容。
trx id | trx state | trx started | trx requested lock id | trx wait started | trx weight | trx mysql thread id | trx query |
---|---|---|---|---|---|---|---|
A3 |
RUNNING |
2008-01-15 16:44:54 |
NULL |
NULL |
2 |
5 |
SELECT SLEEP(100) |
A4 |
LOCK WAIT |
2008-01-15 16:45:09 |
A4:1:3:2 |
2008-01-15 16:45:09 |
2 |
6 |
SELECT b FROM t FOR UPDATE |
A5 |
锁等待 |
2008-01-15 16:45:14 |
A5:1:3:2 |
2008-01-15 16:45:14 |
2 |
7 |
SELECT c FROM t FOR UPDATE |
以下表格显示了 data_locks
表的一些示例内容。
lock id | lock trx id | lock mode | lock type | lock schema | lock table | lock index | lock data |
---|---|---|---|---|---|---|---|
A3:1:3:2 |
A3 |
X |
记录 |
test |
t |
PRIMARY |
0x0200 |
A4:1:3:2 |
A4 |
X |
记录 |
test |
t |
PRIMARY |
0x0200 |
A5:1:3:2 |
A5 |
X |
记录 |
test |
t |
PRIMARY |
0x0200 |
以下表格显示了 data_lock_waits
表的一些示例内容。
在识别阻塞事务时,如果会话变为空闲,阻塞查询将报告 NULL 值。在这种情况下,使用以下步骤来确定阻塞查询:
-
确定阻塞事务的进程列表 ID。在
sys.innodb_lock_waits
表中,阻塞事务的进程列表 ID 是blocking_pid
值。 -
使用
blocking_pid
,查询 MySQL Performance Schemathreads
表以确定阻塞事务的THREAD_ID
。例如,如果blocking_pid
是 6,发出以下查询:SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID = 6;
-
使用
THREAD_ID
,查询 Performance Schemaevents_statements_current
表以确定最后执行的查询。例如,如果THREAD_ID
是 28,发出以下查询:SELECT THREAD_ID, SQL_TEXT FROM performance_schema.events_statements_current WHERE THREAD_ID = 28\G
-
如果最后执行的查询不足以确定锁的持有原因,可以查询 Performance Schema
events_statements_history
表以查看最后 10 个执行的语句。SELECT THREAD_ID, SQL_TEXT FROM performance_schema.events_statements_history WHERE THREAD_ID = 28 ORDER BY EVENT_ID;
有时,关联内部 InnoDB 锁信息与 MySQL 维护的会话级信息非常有用。例如,您可能想知道,给定 InnoDB 事务 ID,对应的 MySQL 会话 ID 和可能持有锁的会话名称,从而阻塞其他事务。
以下来自 INFORMATION_SCHEMA
INNODB_TRX
表和 Performance Schema data_locks
和 data_lock_waits
表的输出来自一个有点繁忙的系统。如可以看到,有多个事务正在运行。
以下 data_locks
和 data_lock_waits
表显示:
可能存在 INFORMATION_SCHEMA
PROCESSLIST
和 INNODB_TRX
表之间的不一致。有关解释,请参阅 第 17.15.2.3 节,“InnoDB 事务和锁定信息的一致性和持久性”。
以下表显示了 PROCESSLIST
表的内容,对于一个运行繁忙工作负载的系统。
ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
---|---|---|---|---|---|---|---|
384 |
root |
localhost |
test |
Query |
10 |
update |
INSERT INTO t2 VALUES … |
257 |
root |
localhost |
test |
Query |
3 |
update |
INSERT INTO t2 VALUES … |
130 |
root |
localhost |
test |
Query |
0 |
update |
INSERT INTO t2 VALUES … |
61 |
root |
localhost |
test |
Query |
1 |
update |
INSERT INTO t2 VALUES … |
8 |
root |
本地主机 |
测试 |
查询 |
1 |
更新 |
INSERT INTO t2 VALUES … |
4 |
root |
本地主机 |
测试 |
查询 |
0 |
准备 |
SELECT * FROM PROCESSLIST |
2 |
root |
本地主机 |
测试 |
睡眠 |
566 |
|
NULL |
以下表格显示了在系统运行繁重 INNODB_TRX 表的内容。
trx id | trx state | trx started | trx requested lock id | trx wait started | trx weight | trx mysql thread id | trx query |
---|---|---|---|---|---|---|---|
77F |
锁定等待 |
2008-01-15 13:10:16 |
77F |
2008-01-15 13:10:16 |
1 |
876 |
INSERT INTO t09 (D, B, C) VALUES … |
77E |
锁定等待 |
2008-01-15 13:10:16 |
77E |
2008-01-15 13:10:16 |
1 |
875 |
INSERT INTO t09 (D, B, C) VALUES … |
77D |
锁定等待 |
2008-01-15 13:10:16 |
77D |
2008-01-15 13:10:16 |
1 |
874 |
INSERT INTO t09 (D, B, C) VALUES … |
77B |
锁定等待 |
2008-01-15 13:10:16 |
77B:733:12:1 |
2008-01-15 13:10:16 |
4 |
873 |
INSERT INTO t09 (D, B, C) VALUES … |
77A |
运行中 |
2008-01-15 13:10:16 |
NULL |
NULL |
4 |
872 |
SELECT b, c FROM t09 WHERE … |
E56 |
锁定等待 |
2008-01-15 13:10:06 |
E56:743:6:2 |
2008-01-15 13:10:06 |
5 |
384 |
INSERT INTO t2 VALUES … |
E55 |
锁定等待 |
2008-01-15 13:10:06 |
E55:743:38:2 |
2008-01-15 13:10:13 |
965 |
257 |
INSERT INTO t2 VALUES … |
19C |
运行中 |
2008-01-15 13:09:10 |
NULL |
NULL |
2900 |
130 |
INSERT INTO t2 VALUES … |
E15 |
运行中 |
2008-01-15 13:08:59 |
NULL |
NULL |
5395 |
61 |
INSERT INTO t2 VALUES … |
51D |
运行中 |
2008-01-15 13:08:47 |
NULL |
NULL |
9807 |
8 |
INSERT INTO t2 VALUES … |
以下表格显示了在运行重负载data_lock_waits
表的内容工作负载。
requesting trx id | requested lock id | blocking trx id | blocking lock id |
---|---|---|---|
77F |
77F:806 |
77E |
77E:806 |
77F |
77F:806 |
77D |
77D:806 |
77F |
77F:806 |
77B |
77B:806 |
77E |
77E:806 |
77D |
77D:806 |
77E |
77E:806 |
77B |
77B:806 |
77D |
77D:806 |
77B |
77B:806 |
77B |
77B:733:12:1 |
77A |
77A:733:12:1 |
E56 |
E56:743:6:2 |
E55 |
E55:743:6:2 |
E55 |
E55:743:38:2 |
19C |
19C:743:38:2 |
以下表格显示了data_locks
表的内容,用于系统运行重负载工作负载。
lock id | lock trx id | lock mode | lock type | lock schema | lock table | lock index | lock data |
---|---|---|---|---|---|---|---|
77F:806 |
77F |
AUTO_INC |
TABLE |
test |
t09 |
NULL |
NULL |
77E:806 |
77E |
AUTO_INC |
TABLE |
test |
t09 |
NULL |
NULL |
77D:806 |
77D |
AUTO_INC |
TABLE |
test |
t09 |
NULL |
NULL |
77B:806 |
77B |
AUTO_INC |
TABLE |
test |
t09 |
NULL |
NULL |
77B:733:12:1 |
77B |
X |
RECORD |
test |
t09 |
PRIMARY |
supremum pseudo-record |
77A:733:12:1 |
77A |
X |
RECORD |
test |
t09 |
PRIMARY |
supremum pseudo-record |
E56:743:6:2 |
E56 |
S |
RECORD |
test |
t2 |
PRIMARY |
0, 0 |
E55:743:6:2 |
E55 |
X |
RECORD |
test |
t2 |
PRIMARY |
0, 0 |
E55:743:38:2 |
E55 |
S |
RECORD |
test |
t2 |
PRIMARY |
1922, 1922 |
19C:743:38:2 |
19C |
X |
RECORD |
test |
t2 |
PRIMARY |
1922, 1922 |