How to find blocking InnoDB connections in MySQL and then kill those connections
As of MySQL 5.5, you can use these 2 INFORMATION_SCHEMA views :
- INNODB_LOCK_WAITS
- INNODB_TRX
Here is an example:
session 1
create table t(id int not null auto_increment, c1 int, primary key(id));
insert into t(id,c1) values (1,1);
set autocommit = 0;
update t set c1 = 2 where id = 1;
session 2
update t set c1 = 3 where id = 1;
You can see that:
mysql> select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 60A9
trx_state: LOCK WAIT
trx_started: 2012-02-23 12:50:22
trx_requested_lock_id: 60A9:4658:3:2
trx_wait_started: 2012-02-23 12:50:22
trx_weight: 2
trx_mysql_thread_id: 849
trx_query: update t set c1 = 3 where id = 1
trx_operation_state: starting index read
trx_tables_in_use: 1
trx_tables_locked: 1
trx_lock_structs: 2
trx_lock_memory_bytes: 376
trx_rows_locked: 1
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 10000
*************************** 2. row ***************************
trx_id: 60A8
trx_state: RUNNING
trx_started: 2012-02-23 12:49:32
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 3
trx_mysql_thread_id: 848
trx_query: select * from information_schema.innodb_trx
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 2
trx_lock_memory_bytes: 376
trx_rows_locked: 1
trx_rows_modified: 1
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 10000
2 rows in set (0.52 sec)
mysql> select * from information_schema.innodb_lock_waits\G
*************************** 1. row ***************************
requesting_trx_id: 60A9
requested_lock_id: 60A9:4658:3:2
blocking_trx_id: 60A8
blocking_lock_id: 60A8:4658:3:2
1 row in set (0.00 sec)
Transaction 60A8 is blocking 60A9. So if you want to kill 60A8, you need to kill the trx_mysql_thread_id of that transaction:
$ kill 848;
When you have a lot of transactions, you can use this statement:
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;
This way, you can see the waiting_thread and the blocking_thread.