1. 程式人生 > >MySQL 死鎖檢查處理

MySQL 死鎖檢查處理

正常情況下,死鎖發生時,權重最小的連線將被kill並回滾。但是為了找出語句來優化,啟用可啟用死鎖將死鎖資訊記錄下來。

#step 1:視窗一
mysql> start transaction;
mysql> update aa set name='aaa' where id = 1;

#step 2:視窗二
mysql> start transaction;
mysql> update bb set name='bbb' where id = 1;

#step 3:視窗一
mysql> update bb set name='bbb';
#step 4:視窗三
#是否自動提交
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+

#檢視當前連線
mysql> show processlist;
mysql> show full processlist;
mysql> SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;
+----+------+-----------+------+---------+------+-------+------------------+
| Id | User | Host      | db   | Command | Time | State | Info             |
+----+------+-----------+------+---------+------+-------+------------------+
|  4 | root | localhost | test | Sleep   |  244 |       | NULL             |
|  5 | root | localhost | test | Sleep   |  111 |       | NULL             |
|  6 | root | localhost | NULL | Query   |    0 | init  | show processlist |
+----+------+-----------+------+---------+------+-------+------------------+


#檢視當前正在被鎖的事務(鎖請求超時後則查不到)
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+
| lock_id          | lock_trx_id | lock_mode | lock_type | lock_table  | lock_index      | lock_space | lock_page | lock_rec | lock_data      |
+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+
| 130718495:65:3:4 | 130718495   | X         | RECORD    | `test`.`bb` | GEN_CLUST_INDEX |         65 |         3 |        4 | 0x000000000300 |
| 130718496:65:3:4 | 130718496   | X         | RECORD    | `test`.`bb` | GEN_CLUST_INDEX |         65 |         3 |        4 | 0x000000000300 |
+------------------+-------------+-----------+-----------+-------------+-----------------+------------+-----------+----------+----------------+

#檢視當前等待鎖的事務(鎖請求超時後則查不到)
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 130718499         | 130718499:65:3:4  | 130718500       | 130718500:65:3:4 |
+-------------------+-------------------+-----------------+------------------+


#檢視當前未提交的事務(如果死鎖等待超時,事務可能還沒有關閉)
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
+--------------------------------------------------------------------------------------------------------+
| trx_id    | trx_state | trx_started         | trx_requested_lock_id | trx_wait_started    | trx_weight |
+-----------+-----------+---------------------+-----------------------+---------------------+------------+
| 130718500 | RUNNING   | 2018-03-12 09:28:10 | NULL                  | NULL                |          3 |
| 130718499 | LOCK WAIT | 2018-03-12 09:27:59 | 130718499:65:3:4      | 2018-03-12 09:32:48 |          5 |
==========================================================================================================
| trx_mysql_thread_id | trx_query                             | trx_operation_state | trx_tables_in_use |
+---------------------+---------------------------------------+---------------------+-------------------+
|                   4 | NULL                                  | NULL                |                 0 |
|                   5 | update bb set name='bbb'              | starting index read |                 1 |
=========================================================================================================
| trx_tables_locked | trx_lock_structs | trx_lock_memory_bytes | trx_rows_locked | trx_rows_modified |
+-------------------+------------------+-----------------------+-----------------+-------------------+
|                 0 |                2 |                   360 |               3 |                 1 |
|                 1 |                4 |                  1184 |               4 |                 1 |
===========================================================================================================================
| trx_concurrency_tickets | trx_isolation_level | trx_unique_checks | trx_foreign_key_checks | trx_last_foreign_key_error |
+-------------------------+---------------------+-------------------+------------------------+----------------------------+
|                       0 | REPEATABLE READ     |                 1 |                      1 | NULL                       |
|                       0 | REPEATABLE READ     |                 1 |                      1 | NULL                       |
===========================================================================================================================
| trx_adaptive_hash_latched | trx_adaptive_hash_timeout | trx_is_read_only | trx_autocommit_non_locking |
+---------------------------+---------------------------+------------------+----------------------------+
|                         0 |                     10000 |                0 |                          0 |
|                         0 |                     10000 |                0 |                          0 |
+---------------------------+---------------------------+------------------+----------------------------+


#檢視正在被訪問的表
mysql> show OPEN TABLES where In_use > 0;
+----------+-------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+-------+--------+-------------+
| test     | bb    |      1 |           0 |
+----------+-------+--------+-------------+
#step 3:視窗一 (若第三步中鎖請求太久,則出現鎖超時而終止執行)
mysql> update bb set name='bbb';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction


#"視窗一" 鎖請求超時前,執行第五步,使死鎖產生,則該連線 "視窗二" 執行終止,"視窗一" 順利執行
#step 5:視窗二
mysql> update aa set name='aa';
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
檢視最近一個死鎖情況
#檢視最近一個死鎖情況
mysql> SHOW ENGINE INNODB STATUS\G ;
...............
------------------------
LATEST DETECTED DEADLOCK
------------------------
2018-03-12 11:01:06 7ffb4993a700 #發生時間
*** (1) TRANSACTION: #事務1
TRANSACTION 130718515, ACTIVE 19 sec starting index read
mysql tables in use 1, locked 1 #正被訪問的表
LOCK WAIT 4 lock struct(s), heap size 1184, 4 row lock(s), undo log entries 1 #影響行數
MySQL thread id 5, OS thread handle 0x7ffb498f8700, query id 205 localhost root updating #執行緒/連線host/使用者
update bb set name='bb' #請求語句
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: #等待以下資源 (鎖定位置及鎖模式)
RECORD LOCKS space id 65 page no 3 n bits 72 index `GEN_CLUST_INDEX` of table `test`.`bb` trx id 130718515 lock_mode X waiting
Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000000000300; asc       ;;
 1: len 6; hex 000007ca9b34; asc      4;;
 2: len 7; hex 1f000002092075; asc       u;;
 3: len 4; hex 80000001; asc     ;;
 4: len 2; hex 6262; asc bb;;

*** (2) TRANSACTION: #事務2
TRANSACTION 130718516, ACTIVE 14 sec starting index read
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1184, 4 row lock(s), undo log entries 1
MySQL thread id 4, OS thread handle 0x7ffb4993a700, query id 206 localhost root updating
update aa set name='aa' #請求語句
*** (2) HOLDS THE LOCK(S): #持有鎖資源
RECORD LOCKS space id 65 page no 3 n bits 72 index `GEN_CLUST_INDEX` of table `test`.`bb` trx id 130718516 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000000000301; asc       ;;
 1: len 6; hex 000007ca9b17; asc       ;;
 2: len 7; hex 9000000144011e; asc     D  ;;
 3: len 4; hex 80000002; asc     ;;
 4: len 2; hex 6262; asc bb;;

Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000000000300; asc       ;;
 1: len 6; hex 000007ca9b34; asc      4;;
 2: len 7; hex 1f000002092075; asc       u;;
 3: len 4; hex 80000001; asc     ;;
 4: len 2; hex 6262; asc bb;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 64 page no 3 n bits 80 index `GEN_CLUST_INDEX` of table `test`.`aa` trx id 130718516 lock_mode X waiting
Record lock, heap no 7 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 6; hex 000000000200; asc       ;;
 1: len 6; hex 000007ca9b33; asc      3;;
 2: len 7; hex 1e000001d53057; asc      0W;;
 3: len 4; hex 80000001; asc     ;;
 4: len 2; hex 6161; asc aa;;

*** WE ROLL BACK TRANSACTION (2)
...............
#死鎖記錄只記錄最近一個死鎖資訊,若要將每個死鎖資訊都儲存到錯誤日誌,啟用以下引數:
mysql> show variables like 'innodb_print_all_deadlocks';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_print_all_deadlocks | OFF   |
+----------------------------+-------+

 
#上面 【step 3:視窗一】若一直請求不到資源,預設50秒則出現鎖等待超時。
mysql> show variables like 'innodb_lock_wait_timeout'; 
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50    |
+--------------------------+-------+

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction


#設定全域性變數 鎖等待超時為60秒(新的連線生效)
#mysql> set session innodb_lock_wait_timeout=50; 
mysql> set global innodb_lock_wait_timeout=60; 


#上面測試中,當事務中的某個語句超時只回滾該語句,事務的完整性屬於被破壞了。為了回滾這個事務,啟用以下引數:
mysql> show variables like 'innodb_rollback_on_timeout';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_rollback_on_timeout | OFF   |
+----------------------------+-------+
最終引數設定如下:(重啟服務重新連線測試)
[mysqld]
log-error =/var/log/mysqld3306.log
innodb_lock_wait_timeout=60     #鎖請求超時時間(秒)
innodb_rollback_on_timeout = 1  #事務中某個語句鎖請求超時將回滾真個事務
innodb_print_all_deadlocks = 1  #死鎖都儲存到錯誤日誌
#若手動刪除堵塞會話,刪除 Command='Sleep' 、無State、無Info、trx_weight 權重最小的。
show processlist;
SELECT trx_mysql_thread_id,trx_state,trx_started,trx_weight FROM INFORMATION_SCHEMA.INNODB_TRX;