应用-找出谁持有行锁
时间:2021-04-13 12:13:46
收藏:0
阅读:0
该案例中涉及performance_schema.data_locks表是MySQL8.0中新增的,8.0之前的版本不支持,如果一个事物长时间未提交,我们虽然可以从information_schema.innodb_trx、performance_schema.events_transactions_current等表中查询到相应的事务信息,但却无从知道这个事务持有了哪些锁。虽然information_schema.innodb_locks表是用于记录事务的锁信息的,但需要在两个不同的事务发生锁等待时该表才会记录两个事务的锁信息。从8.0开始提供了performance_schema.data_locks表用于记录任意事务的锁信息(同时废弃了information_schema.innodb_locks表),不需要有锁等待关系存在(注意:该表中只记录InnoDB存储引擎层的锁)。
会话一:显示开启一个事务
use test; select * from test; begin; update test set xxx
开启会话二:
use test; select * from test; begin; update test set name = ‘yao‘ where id = 1;
会话三:查询data_locks表
mysql> select * from performance_schema.data_locks; +--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+ | ENGINE | ENGINE_LOCK_ID | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA | +--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+ | INNODB | 140114224791792:1061:140114114198880 | 1561 | 88 | 15 | test | test | NULL | NULL | NULL | 140114114198880 | TABLE | IX | GRANTED | NULL | | INNODB | 140114224791792:2:4:2:140114114195776 | 1561 | 88 | 15 | test | test | NULL | NULL | PRIMARY | 140114114195776 | RECORD | X,REC_NOT_GAP | WAITING | 1 | | INNODB | 140114224790936:1061:140114114192720 | 1560 | 87 | 18 | test | test | NULL | NULL | NULL | 140114114192720 | TABLE | IX | GRANTED | NULL | | INNODB | 140114224790936:2:4:2:140114114189616 | 1560 | 87 | 18 | test | test | NULL | NULL | PRIMARY | 140114114189616 | RECORD | X,REC_NOT_GAP | GRANTED | 1 | +--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+ 4 rows in set (0.01 sec)
我们查看sys.innodb_lock_waits
mysql> select * from sys.innodb_lock_waits; +---------------------+----------+---------------+---------------+---------------------+-------------------+------------------------+---------------------------+--------------+-------------+----------------+---------------------+-----------------+-------------------------+---------------------------+-------------+-------------------------------------------+---------------------------------------+-------------------+-----------------+--------------+----------------+---------------------------------------+--------------------+----------------------+------------------+--------------------------+----------------------------+-------------------------+------------------------------+ | wait_started | wait_age | wait_age_secs | locked_table | locked_table_schema | locked_table_name | locked_table_partition | locked_table_subpartition | locked_index | locked_type | waiting_trx_id | waiting_trx_started | waiting_trx_age | waiting_trx_rows_locked | waiting_trx_rows_modified | waiting_pid | waiting_query | waiting_lock_id | waiting_lock_mode | blocking_trx_id | blocking_pid | blocking_query | blocking_lock_id | blocking_lock_mode | blocking_trx_started | blocking_trx_age | blocking_trx_rows_locked | blocking_trx_rows_modified | sql_kill_blocking_query | sql_kill_blocking_connection | +---------------------+----------+---------------+---------------+---------------------+-------------------+------------------------+---------------------------+--------------+-------------+----------------+---------------------+-----------------+-------------------------+---------------------------+-------------+-------------------------------------------+---------------------------------------+-------------------+-----------------+--------------+----------------+---------------------------------------+--------------------+----------------------+------------------+--------------------------+----------------------------+-------------------------+------------------------------+ | 2021-03-15 10:26:04 | 00:00:23 | 23 | `test`.`test` | test | test | NULL | NULL | PRIMARY | RECORD | 1561 | 2021-03-15 10:13:12 | 00:13:15 | 5 | 0 | 49 | update test set name = ‘yao‘ where id = 1 | 140114224791792:2:4:2:140114114197152 | X,REC_NOT_GAP | 1560 | 48 | NULL | 140114224790936:2:4:2:140114114189616 | X,REC_NOT_GAP | 2021-03-15 09:51:26 | 00:35:01 | 1 | 1 | KILL QUERY 48 | KILL 48 | +---------------------+----------+---------------+---------------+---------------------+-------------------+------------------------+---------------------------+--------------+-------------+----------------+---------------------+-----------------+-------------------------+---------------------------+-------------+-------------------------------------------+---------------------------------------+-------------------+-----------------+--------------+----------------+---------------------------------------+--------------------+----------------------+------------------+--------------------------+----------------------------+-------------------------+------------------------------+ 1 row in set (0.00 sec)
innodb_lock_waits
提示:在MySQL5.7版本中,也可以使用sys.innodb_lock_waits试图查看,但是在MySQL8.0中,该视图连接查询的表不同(把之前版本中使用的information_schema.innodb_locks表和information_schema.innodb_lock_waits)表替换为了performance_schema.data_locks和performance_schema.data_lock_waits表。另外,在MySQL5.6及之前的版本中,默认没有sys库,我们可以使用如下语句代替。
5.6 查询行锁脚本
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, r1.lock_index as locked_index, r1.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, sys.format_statement(r.trx_query) As waiting_query, r1.lock_id As waiting_lock_id, r1.lock_mode as waiting_lock_mode, b.trx_id as blocking_trx_id, b.trx_mysql_thread_id as blocking_pid, sys.format_statement(b.trx_query) as blocking_query, 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 inner join information_schema.innodb_trx b on b.trx_id = w.blocking_trx_id inner join information_schema.innodb_trx r on r.trx_id = w.requesting_trx_id inner join information_schema.innodb_locks bl on bl.lock_id = w.blocking_lock_id inner join information_schema.innodb_locks rl on rl.lock_id = w.requested_lock_id order by r.trx_wait_started;
5.7
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 information_schema.`INNODB_LOCK_WAITS` w INNER JOIN information_schema.`INNODB_TRX` b ON b.`trx_id` = w.`blocking_trx_id` INNER JOIN information_schema.`INNODB_TRX` r ON r.`trx_id` = w.`requesting_trx_id`;
8.0查询行锁脚本
## 查询waiting信息 select * from sys.innodb_lock_waits; ## 查看blocking session历史信息 select c.THREAD_ID, c.event_name, c.TIMER_WAIT / 1000 / 1000 / 1000 / 1000 as "TIMER_WAIT_S", c.sql_text, c.CURRENT_SCHEMA, c.OBJECT_NAME from performance_schema.events_statements_history c where c.THREAD_ID in ( select t.THREAD_ID from sys.innodb_lock_waits ilw inner join performance_schema.threads t on t.PROCESSLIST_ID = ilw.blocking_pid) order by c.TIMER_START;
评论(0)