1. 查詢方式1(5.7及之前版本可以通過該語句查詢)
1)以下查詢正常使用的前提條件
## 前提要開啓相關監控項
update setup_instruments set ENABLED='YES',TIMED='YES' where name like 'statement/sql%';
update setup_consumers set ENABLED='YES' where name like 'events_statements%';
2)innodb行鎖阻塞查詢語句
set group_concat_max_len=20480;
SELECT
`r`.`trx_wait_started` AS `wait_started`,
TIMEDIFF(NOW(), `r`.`trx_wait_started`) AS `wait_age`,
TIMESTAMPDIFF(SECOND,
`r`.`trx_wait_started`,
NOW()) AS `wait_age_secs`,
`rl`.`lock_table` AS `locked_table`,
`rl`.`lock_index` AS `locked_index`,
`rl`.`lock_type` AS `locked_type`,
`r`.`trx_id` AS `waiting_trx_id`,
`r`.`trx_started` AS `waiting_trx_started`,
TIMEDIFF(NOW(), `r`.`trx_started`) AS `waiting_trx_age`,
`r`.`trx_rows_locked` AS `waiting_trx_rows_locked`,
`r`.`trx_rows_modified` AS `waiting_trx_rows_modified`,
`r`.`trx_mysql_thread_id` AS `waiting_pid`,
`r`.`trx_query` AS `waiting_query`,
(select group_concat(tem_r.sql_text order by EVENT_ID SEPARATOR ';\n') from (select thread_id,sql_text,EVENT_ID from performance_schema.events_statements_history his union select thread_id,sql_text,EVENT_ID from performance_schema.events_statements_current cur) tem_r where tem_r.thread_id=r2.thread_id) waiting_trx_statements,
`rl`.`lock_id` AS `waiting_lock_id`,
`rl`.`lock_mode` AS `waiting_lock_mode`,
`b`.`trx_id` AS `blocking_trx_id`,
`b`.`trx_mysql_thread_id` AS `blocking_pid`,
`b`.`trx_query` AS `blocking_query`,
(select group_concat(tem_b.sql_text order by EVENT_ID SEPARATOR ';\n') from (select thread_id,sql_text,EVENT_ID from performance_schema.events_statements_history his union select thread_id,sql_text,EVENT_ID from performance_schema.events_statements_current cur) tem_b where tem_b.thread_id=b2.thread_id) blocking_trx_statements,
`bl`.`lock_id` AS `blocking_lock_id`,
`bl`.`lock_mode` AS `blocking_lock_mode`,
`b`.`trx_started` AS `blocking_trx_started`,
TIMEDIFF(NOW(), `b`.`trx_started`) AS `blocking_trx_age`,
`b`.`trx_rows_locked` AS `blocking_trx_rows_locked`,
`b`.`trx_rows_modified` AS `blocking_trx_rows_modified`,
CONCAT('KILL QUERY ', `b`.`trx_mysql_thread_id`) AS `sql_kill_blocking_query`,
CONCAT('KILL ', `b`.`trx_mysql_thread_id`) AS `sql_kill_blocking_connection`
FROM
`information_schema`.`innodb_lock_waits` `w`
JOIN `information_schema`.`innodb_trx` `b` ON `b`.`trx_id` = `w`.`blocking_trx_id`
JOIN `information_schema`.`innodb_trx` `r` ON `r`.`trx_id` = `w`.`requesting_trx_id`
JOIN `information_schema`.`innodb_locks` `bl` ON `bl`.`lock_id` = `w`.`blocking_lock_id`
JOIN `information_schema`.`innodb_locks` `rl` ON `rl`.`lock_id` = `w`.`requested_lock_id`
join `performance_schema`.`threads` b2 on b2.processlist_id=b.trx_mysql_thread_id
join `performance_schema`.`threads` r2 on r2.processlist_id=r.trx_mysql_thread_id
ORDER BY `r`.`trx_wait_started`\G;
2.查詢方式2 (適用版本5.7)
1)前提條件
## 前提要開啓相關監控項
update setup_instruments set ENABLED='YES',TIMED='YES' where name like 'statement/sql%';
update setup_consumers set ENABLED='YES' where name like 'events_statements%';
2)innodb行鎖阻塞查詢語句
set group_concat_max_len=20480;
select
k.wait_started,
k.wait_age,
k.wait_age_secs,
k.locked_table,
k.locked_index,
k.locked_type,
k.waiting_trx_id,
k.waiting_trx_started,
k.waiting_trx_age,
k.waiting_trx_rows_locked,
k.waiting_trx_rows_modified,
k.waiting_pid,
k.waiting_query,
(select group_concat(tem_r.sql_text order by EVENT_ID SEPARATOR ';\n') from (select thread_id,sql_text,EVENT_ID from performance_schema.events_statements_history his union select thread_id,sql_text,EVENT_ID from performance_schema.events_statements_current cur) tem_r where tem_r.thread_id=r.thread_id) waiting_trx_statements,
k.waiting_lock_id,
k.waiting_lock_mode,
k.blocking_trx_id,
k.blocking_pid,
k.blocking_query,
(select group_concat(tem_b.sql_text order by EVENT_ID SEPARATOR ';\n') from (select thread_id,sql_text,EVENT_ID from performance_schema.events_statements_history his union select thread_id,sql_text,EVENT_ID from performance_schema.events_statements_current cur) tem_b where tem_b.thread_id=b.thread_id) blocking_trx_statements,
k.blocking_lock_id,
k.blocking_lock_mode,
k.blocking_trx_started,
k.blocking_trx_age,
k.blocking_trx_rows_locked,
k.blocking_trx_rows_modified,
k.sql_kill_blocking_query,
k.sql_kill_blocking_connection
from sys.innodb_lock_waits k
join `performance_schema`.`threads` b on b.processlist_id=k.blocking_pid
join `performance_schema`.`threads` r on r.processlist_id=k.waiting_pid
ORDER BY k.`wait_started`\G;
NOTE1:在8.0之前只有存在鎖等待`information_schema`.`innodb_lock_waits`和`information_schema`.`innodb_locks`纔會存在記錄
NOTE2:在Mysql 8.0中使用performance_schema.data_locks表和performance_schema.data_lock_waits 表替換了NOTE1中的兩張表
3. Mysql 5.7中行鎖阻塞示例
1)測試表結構及記錄情況
show create table test_lock;
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_lock | CREATE TABLE `test_lock` (
`id` int(11) NOT NULL,
`num` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_num` (`num`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
[[email protected]][test_shao]> select * from test_lock;
+----+------+---------------+
| id | num | name |
+----+------+---------------+
| 4 | 4 | name_8_before |
| 8 | 8 | name_8_before |
| 11 | 11 | name_11 |
+----+------+---------------+
2)會話1執行如下sql
[[email protected]][test_shao]> begin;
Query OK, 0 rows affected (0.00 sec)
[[email protected]][test_shao]> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
| 1013227 |
+-----------------+
1 row in set (0.00 sec)
[[email protected]][test_shao]> update test_lock set name='xxxx' where id=4;
Query OK, 1 row affected (0.06 sec)
Rows matched: 1 Changed: 1 Warnings: 0
3)會話2,會話3 分別執行
update test_lock set name='xxxx' where id=4;
4)查詢阻塞情況
*************************** 1. row ***************************
wait_started: 2020-03-24 16:08:26
wait_age: 00:00:20
wait_age_secs: 20
locked_table: `test_shao`.`test_lock`
locked_index: PRIMARY
locked_type: RECORD
waiting_trx_id: 108345306
waiting_trx_started: 2020-03-24 16:08:26
waiting_trx_age: 00:00:20
waiting_trx_rows_locked: 1
waiting_trx_rows_modified: 0
waiting_pid: 1013231
waiting_query: update test_lock set name='xxxx' where id=4
waiting_trx_statements: select @@version_comment limit 1;
select USER();
update test_lock set name='xxxx' where id=4
waiting_lock_id: 108345306:216:3:10
waiting_lock_mode: X
blocking_trx_id: 108345305
blocking_pid: 1013227
blocking_query: NULL
blocking_trx_statements: select user,host from mysql.user;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED WITH 'mysql_native_password' AS '<secret>';
SELECT DATABASE();
show tables;
show create table test_lock;
select * from test_lock;
begin;
select connection_id();
update test_lock set name='xxxx' where id=4
blocking_lock_id: 108345305:216:3:10
blocking_lock_mode: X
blocking_trx_started: 2020-03-24 16:08:24
blocking_trx_age: 00:00:22
blocking_trx_rows_locked: 1
blocking_trx_rows_modified: 1
sql_kill_blocking_query: KILL QUERY 1013227
sql_kill_blocking_connection: KILL 1013227
*************************** 2. row ***************************
wait_started: 2020-03-24 16:08:28
wait_age: 00:00:18
wait_age_secs: 18
locked_table: `test_shao`.`test_lock`
locked_index: PRIMARY
locked_type: RECORD
waiting_trx_id: 108345307
waiting_trx_started: 2020-03-24 16:08:28
waiting_trx_age: 00:00:18
waiting_trx_rows_locked: 1
waiting_trx_rows_modified: 0
waiting_pid: 1013232
waiting_query: update test_lock set name='xxxx' where id=4
waiting_trx_statements: select @@version_comment limit 1;
select USER();
update test_lock set name='xxxx' where id=4
waiting_lock_id: 108345307:216:3:10
waiting_lock_mode: X
blocking_trx_id: 108345305
blocking_pid: 1013227
blocking_query: NULL
blocking_trx_statements: select user,host from mysql.user;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED WITH 'mysql_native_password' AS '<secret>';
SELECT DATABASE();
show tables;
show create table test_lock;
select * from test_lock;
begin;
select connection_id();
update test_lock set name='xxxx' where id=4
blocking_lock_id: 108345305:216:3:10
blocking_lock_mode: X
blocking_trx_started: 2020-03-24 16:08:24
blocking_trx_age: 00:00:22
blocking_trx_rows_locked: 1
blocking_trx_rows_modified: 1
sql_kill_blocking_query: KILL QUERY 1013227
sql_kill_blocking_connection: KILL 1013227
*************************** 3. row ***************************
wait_started: 2020-03-24 16:08:28
wait_age: 00:00:18
wait_age_secs: 18
locked_table: `test_shao`.`test_lock`
locked_index: PRIMARY
locked_type: RECORD
waiting_trx_id: 108345307
waiting_trx_started: 2020-03-24 16:08:28
waiting_trx_age: 00:00:18
waiting_trx_rows_locked: 1
waiting_trx_rows_modified: 0
waiting_pid: 1013232
waiting_query: update test_lock set name='xxxx' where id=4
waiting_trx_statements: select @@version_comment limit 1;
select USER();
update test_lock set name='xxxx' where id=4
waiting_lock_id: 108345307:216:3:10
waiting_lock_mode: X
blocking_trx_id: 108345306
blocking_pid: 1013231
blocking_query: update test_lock set name='xxxx' where id=4
blocking_trx_statements: select @@version_comment limit 1;
select USER();
update test_lock set name='xxxx' where id=4
blocking_lock_id: 108345306:216:3:10
blocking_lock_mode: X
blocking_trx_started: 2020-03-24 16:08:26
blocking_trx_age: 00:00:20
blocking_trx_rows_locked: 1
blocking_trx_rows_modified: 0
sql_kill_blocking_query: KILL QUERY 1013231
sql_kill_blocking_connection: KILL 1013231
3 rows in set, 3 warnings (0.01 sec)
ERROR:
No query specified
##第一個會話中未提交的事務阻塞了第二個會話中的update,第一個及第二個會話又阻塞了第三個會話的update