1. 程式人生 > >mysql死鎖排查

mysql死鎖排查

死鎖

  • show engine innodb status;顯示引擎引數,查死鎖sql
  • show engine innodb mutex;
LATEST DETECTED DEADLOCK
------------------------
2017-01-21 23:00:32 2b4ad8705700
*** (1) TRANSACTION:
TRANSACTION 74247262250, ACTIVE 0 sec starting index read
mysql tables in use 2, locked 2
LOCK WAIT 8 lock struct(s), heap size
1184, 7 row lock(s) MySQL thread id 4808396, OS thread handle 0x2b4a72923700, query id 77966678624 10.150.135.191 cbu_cms Sending data update pool_offer t1, pool_offer_batch t2 set t1.score=t2.score where t1.pool_id=t2.pool_id and t1.offer_id=t2.offer_id and t2.batch_id='ichoose-221556405-1484989224443'
*** (1) HOLDS THE LOCK(S): RECORD LOCKS space id 566 page no 107635 n bits 464 index `ind_pidoid` of table `cbu_cms`.`pool_offer` trx id 74247262250 lock_mode X locks rec but not gap Record lock, heap no 220 PHYSICAL RECORD: n_fields 3;
compact format; info bits 0 0: len 8; hex 0000000000004acf; asc J ;; 1: len 8; hex 0000000039f5e41c; asc 9 ;; 2: len 8; hex 0000000003f74e7c; asc N|;; *** (1) WAITING FOR THIS LOCK
TO BE GRANTED: RECORD LOCKS space id 566 page no 107635 n bits 464 index `ind_pidoid` of table `cbu_cms`.`pool_offer` trx id 74247262250 lock_mode X locks rec but not gap waiting Record lock, heap no 337 PHYSICAL RECORD: n_fields 3;
compact format; info bits 0 0: len 8; hex 0000000000004acf; asc J ;; 1: len 8; hex 000000003d236748; asc =#gH;; 2: len 8; hex 0000000003fabe1d; asc ;; *** (2) TRANSACTION: TRANSACTION 74247262209, ACTIVE 0 sec inserting, thread declared inside InnoDB 4685 mysql tables in use 2, locked 1 45 lock struct(s), heap size 6544, 159 row lock(s), undo log entries 80 MySQL thread id 4808449, OS thread handle 0x2b4ad8705700, query id 77966678347 11.136.33.169 cbu_cms Creating sort index insert into pool_offer (enter_way,gmt_create,gmt_modified,pool_id,offer_id,member_id,category_id,category1_id,category2_id,category3_id,bu_id,expired_time,offerstatus,sort,gmt_sort,status,ds_tag,location) select 'dsimport' as enter_way,gmt_create,gmt_modified,pool_id,offer_id,member_id,category_id,category1_id,category2_id,category3_id,bu_id,expired_time,offerstatus,sort,gmt_modified,'NORMAL' as status,ds_tag,location from pool_offer_batch where batch_id='import-offer-25767666-1484989291643' and pool_id=19151 order by id on duplicate key update gmt_modified=now(),gmt_sort=values(gmt_modified),sort=values(sort), expired_time=values(expired_time),offerstatus=values(offerstatus),ds_tag=values(ds_tag), location = values(location), category_id = values(category_id), category1_id = values(category1_id), category2_id = values(category2_id), category3_id = values(cate *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 566 page no 107635 n bits 464 index `ind_pidoid` of table `cbu_cms`.`pool_offer` trx id 74247262209 lock_mode X Record lock, heap no 30 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 8; hex 0000000000004acf; asc J ;; 1: len 8; hex 0000000a39f8a858; asc 9 X;; 2: len 8; hex 0000000004086d36; asc m6;; *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 566 page no 107635 n bits 464 index `ind_pidoid` of table `cbu_cms`.`pool_offer` trx id 74247262209 lock_mode X waiting Record lock, heap no 220 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 8; hex 0000000000004acf; asc J ;; 1: len 8; hex 0000000039f5e41c; asc 9 ;; 2: len 8; hex 0000000003f74e7c; asc N|;;

表結構

| pool_offer | CREATE TABLE `pool_offer` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '??',
  `gmt_create` datetime NOT NULL COMMENT '????',
  `gmt_modified` datetime NOT NULL COMMENT '????',
  `pool_id` bigint(20) unsigned DEFAULT NULL COMMENT '??ID',
  `offer_id` bigint(20) unsigned DEFAULT NULL COMMENT '??ID',
  `member_id` varchar(128) DEFAULT NULL COMMENT '??id',
  `status` varchar(64) DEFAULT NULL COMMENT '??',
  `del_operator` varchar(64) DEFAULT NULL COMMENT '?????',
  `creator` varchar(64) DEFAULT NULL COMMENT '?????',
  `modifier` varchar(64) DEFAULT NULL COMMENT '?????',
  `gmt_deleted` date DEFAULT NULL COMMENT '????',
  `enter_way` varchar(64) DEFAULT NULL COMMENT '??????',
  `sort` bigint(20) DEFAULT NULL COMMENT '??',
  `gmt_sort` datetime DEFAULT NULL COMMENT '????',
  `category_id` varchar(128) DEFAULT NULL COMMENT '????id',
  `category1_id` varchar(128) DEFAULT NULL COMMENT '????ID',
  `category2_id` varchar(128) DEFAULT NULL COMMENT '????ID',
  `category3_id` varchar(128) DEFAULT NULL COMMENT '????ID',
  `bu_id` varchar(128) DEFAULT NULL COMMENT 'BU ID',
  `expired_time` datetime DEFAULT NULL COMMENT '????',
  `offerstatus` varchar(30) DEFAULT 'published' COMMENT 'offer??(PUBLISHED???????offerdubbo??)',
  `cheat_flag` int(11) DEFAULT '0' COMMENT '????, 0???5????9???',
  `score` bigint(20) DEFAULT '0' COMMENT '?????????????????????*1000000??',
  `view_sort` bigint(20) DEFAULT NULL COMMENT 'offer??????',
  `conf_sort` bigint(20) DEFAULT NULL COMMENT '???????',
  `ds_tag` varchar(256) DEFAULT NULL COMMENT 'offer??????tag',
  `enroll_id` bigint(20) unsigned DEFAULT NULL COMMENT '??ID',
  `location` varchar(20000) DEFAULT NULL COMMENT '??????????????',
  `hpstatus` varchar(32) DEFAULT NULL COMMENT 'offer?????',
  PRIMARY KEY (`id`),
  UNIQUE KEY `ind_pidoid` (`pool_id`,`offer_id`),
  KEY `ind_memberid` (`member_id`),
  KEY `ind_gmtcreate` (`gmt_create`,`gmt_modified`),
  KEY `ind_gmtsort` (`gmt_sort`),
  KEY `idx_pool_offer_cat` (`pool_id`,`category_id`,`category1_id`,`category2_id`,`category3_id`,`member_id`,`offerstatus`),
  KEY `ind_offerid_status` (`offer_id`,`status`),
  KEY `ind_offer_pool_status` (`offer_id`,`pool_id`,`status`),
  KEY `ind_pidstatus` (`pool_id`,`status`,`ds_tag`(255)),
  KEY `ind_sort` (`pool_id`,`status`,`offerstatus`,`view_sort`,`score`)
) ENGINE=InnoDB AUTO_INCREMENT=67735804 DEFAULT CHARSET=utf8 COMMENT='???offer??' |

鎖超時

  • 報錯
    java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
  • select * from information_schema.innodb_trx\G 找到當前執行的所有事物
  • select * from information_schema.processlist where id =xxx 在processlist裡檢視這個id的執行緒
  • kill掉佔用鎖的執行緒
  • 例子

記得以前,當出現:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction,要解決是一件麻煩的事情;特別是當一個SQL執行完了,但未COMMIT,後面的SQL想要執行就是被鎖,超時結束,DBA光從資料庫無法著手找出源頭是哪個SQL鎖住了;有時候看看 show engine innodb status, 並結合 show full processlist 能暫時解決問題,但一直不能精確定位。

  • 在5.5中,information_schema 庫中增加了三個關於鎖的表(MEMORY引擎):
    • innodb_trx ## 當前執行的所有事務
    • innodb_locks ## 當前出現的鎖
    • innodb_lock_waits ## 鎖等待的對應關係
      看到這個就非常激動,這可是解決了一個大麻煩,先來看一下表結構:
[email protected]127.0.0.1 : information_schema 13:28:38> desc innodb_locks;
+————-+———————+——+—–+———+——-+
| Field       | Type                | Null | Key | Default | Extra |
+————-+———————+——+—–+———+——-+
| lock_id     | varchar(81)         | NO   |     |         |       |#鎖ID
| lock_trx_id | varchar(18)         | NO   |     |         |       |#擁有鎖的事務ID
| lock_mode   | varchar(32)         | NO   |     |         |       |#鎖模式
| lock_type   | varchar(32)         | NO   |     |         |       |#鎖型別
| lock_table  | varchar(1024)       | NO   |     |         |       |#被鎖的表
| lock_index  | varchar(1024)       | YES  |     | NULL    |       |#被鎖的索引
| lock_space  | bigint(21) unsigned | YES  |     | NULL    |       |#被鎖的表空間號
| lock_page   | bigint(21) unsigned | YES  |     | NULL    |       |#被鎖的頁號
| lock_rec    | bigint(21) unsigned | YES  |     | NULL    |       |#被鎖的記錄號
| lock_data   | varchar(8192)       | YES  |     | NULL    |       |#被鎖的資料
+————-+———————+——+—–+———+——-+
10 rows in set (0.00 sec)

[email protected]127.0.0.1 : information_schema 13:28:56> desc innodb_lock_waits;
+——————-+————-+——+—–+———+——-+
| Field             | Type        | Null | Key | Default | Extra |
+——————-+————-+——+—–+———+——-+
| requesting_trx_id | varchar(18) | NO   |     |         |       |#請求鎖的事務ID
| requested_lock_id | varchar(81) | NO   |     |         |       |#請求鎖的鎖ID
| blocking_trx_id   | varchar(18) | NO   |     |         |       |#當前擁有鎖的事務ID
| blocking_lock_id  | varchar(81) | NO   |     |         |       |#當前擁有鎖的鎖ID
+——————-+————-+——+—–+———+——-+
4 rows in set (0.00 sec)

[email protected]127.0.0.1 : information_schema 13:29:05> desc innodb_trx ;
+—————————-+———————+——+—–+———————+——-+
| Field                      | Type                | Null | Key | Default             | Extra |
+—————————-+———————+——+—–+———————+——-+
| trx_id                     | varchar(18)         | NO   |     |                     |       |#事務ID
| trx_state                  | varchar(13)         | NO   |     |                     |       |#事務狀態:
| trx_started                | datetime            | NO   |     | 0000-00-00 00:00:00 |       |#事務開始時間;
| trx_requested_lock_id      | varchar(81)         | YES  |     | NULL                |       |#innodb_locks.lock_id
| trx_wait_started           | datetime            | YES  |     | NULL                |       |#事務開始等待的時間
| trx_weight                 | bigint(21) unsigned | NO   |     | 0                   |       |#
| trx_mysql_thread_id        | bigint(21) unsigned | NO   |     | 0                   |       |#事務執行緒ID
| trx_query                  | varchar(1024)       | YES  |     | NULL                |       |#具體SQL語句
| trx_operation_state        | varchar(64)         | YES  |     | NULL                |       |#事務當前操作狀態
| trx_tables_in_use          | bigint(21) unsigned | NO   |     | 0                   |       |#事務中有多少個表被使用
| trx_tables_locked          | bigint(21) unsigned | NO   |     | 0                   |       |#事務擁有多少個鎖
| trx_lock_structs           | bigint(21) unsigned | NO   |     | 0                   |       |#
| trx_lock_memory_bytes      | bigint(21) unsigned | NO   |     | 0                   |       |#事務鎖住的記憶體大小(B)
| trx_rows_locked            | bigint(21) unsigned | NO   |     | 0                   |       |#事務鎖住的行數
| trx_rows_modified          | bigint(21) unsigned | NO   |     | 0                   |       |#事務更改的行數
| trx_concurrency_tickets    | bigint(21) unsigned | NO   |     | 0                   |       |#事務併發票數
| trx_isolation_level        | varchar(16)         | NO   |     |                     |       |#事務隔離級別
| trx_unique_checks          | int(1)              | NO   |     | 0                   |       |#是否唯一性檢查
| trx_foreign_key_checks     | int(1)              | NO   |     | 0                   |       |#是否外來鍵檢查
| trx_last_foreign_key_error | varchar(256)        | YES  |     | NULL                |       |#最後的外來鍵錯誤
| trx_adaptive_hash_latched  | int(1)              | NO   |     | 0                   |       |#
| trx_adaptive_hash_timeout  | bigint(21) unsigned | NO   |     | 0                   |       |#
+—————————-+———————+——+—–+———————+——-+
22 rows in set (0.01 sec)

下面我們來動手看看資料吧:

  • 建立測試資料:
use test;
create table tx1
(id int primary key ,
c1 varchar(20),
c2 varchar(30))
engine=innodb default charset = utf8 ;

insert into tx1 values
(1,’aaaa’,'aaaaa2′),
(2,’bbbb’,'bbbbb2′),
(3,’cccc’,'ccccc2′);

commit;
  • 產生事務
### Session1
start transaction;
update tx1 set c1=’heyf’,c2=’heyf’ where id = 3;

產生事務,在 innodb_trx 就有資料

[email protected]127.0.0.1 : information_schema 13:38:21> select * from innodb_trx \G
*************************** 1. row ***************************
                    trx_id: 3669D82
                 trx_state: RUNNING
               trx_started: 2010-12-24 13:38:06
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 3
       trx_mysql_thread_id: 2344
                 trx_query: NULL
       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
1 row in set (0.00 sec)

### 由於沒有產生鎖等待,下面兩個表沒有資料
[email protected]127.0.0.1 : information_schema 13:38:31> select * from innodb_lock_waits \G
Empty set (0.00 sec)

[email protected]127.0.0.1 : information_schema 13:38:57> select * from innodb_locks \G
Empty set (0.00 sec)

產生鎖等待

#### session 2
start transaction;
update tx1 set c1=’heyfffff’,c2=’heyffffff’ where id =3 ;

[email protected] : information_schema 13:39:01> select * from innodb_trx \G
*************************** 1. row ***************************
                    trx_id: 3669D83   ##第2個事務
                 trx_state: LOCK WAIT   ## 處於等待狀態
               trx_started: 2010-12-24 13:40:07
     trx_requested_lock_id: 3669D83:49:3:4  ##請求的鎖ID
          trx_wait_started: 2010-12-24 13:40:07
                trx_weight: 2
       trx_mysql_thread_id: 2346       ##執行緒 ID
                 trx_query: update tx1 set c1=’heyfffff’,c2=’heyffffff’ where id =3
       trx_operation_state: starting index read
         trx_tables_in_use: 1      ##需要用到1個表
         trx_tables_locked: 1      ##有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: 3669D82 ##第1個事務
                 trx_state: RUNNING
               trx_started: 2010-12-24 13:38:06
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 3
       trx_mysql_thread_id: 2344
                 trx_query: NULL
       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.00 sec)

[email protected] : information_schema 13:40:12> select * from innodb_locks \G
*************************** 1. row ***************************
    lock_id: 3669D83:49:3:4      ## 第2個事務需要的鎖
lock_trx_id: 3669D83
  lock_mode: X
  lock_type: RECORD
 lock_table: `test`.`tx1`
 lock_index: `PRIMARY`
 lock_space: 49
  lock_page: 3
   lock_rec: 4
  lock_data: 3
*************************** 2. row ***************************
    lock_id: 3669D82:49:3:4     ## 第1個事務需要的鎖
lock_trx_id: 3669D82
  lock_mode: X
  lock_type: RECORD
 lock_table: `test`.`tx1`
 lock_index: `PRIMARY`
 lock_space: 49
  lock_page: 3
   lock_rec: 4
  lock_data: 3
2 rows in set (0.00 sec)

[email protected] : information_schema 13:40:15> select * from innodb_lock_waits \G
*************************** 1. row ***************************
requesting_trx_id: 3669D83         ## 請求鎖的事務
requested_lock_id: 3669D83:49:3:4  ## 請求鎖的鎖ID
  blocking_trx_id: 3669D82         ## 擁有鎖的事務
 blocking_lock_id: 3669D82:49:3:4  ## 擁有鎖的鎖ID
1 row in set (0.00 sec)

參考:
MySQL 加鎖處理分析
一個最不可思議的MySQL死鎖分析