1. 程式人生 > >mysql事務鎖等待時間

mysql事務鎖等待時間

獲取表鎖資訊

SELECT  
    r.trx_id waiting_trx_id,  
    r.trx_mysql_thread_id waiting_thread,  
    TIMESTAMPDIFF(  
        SECOND,  
        r.trx_wait_started,  
        CURRENT_TIMESTAMP  
    ) wait_time,  
    r.trx_query waiting_query,  
    l.lock_table waiting_table_lock,  
    b.trx_id blocking_trx_id,  
    b.trx_mysql_thread_id blocking_thread,  
    SUBSTRING(  
        p. HOST,  
        1,  
        INSTR(p. HOST, ':') - 1  
    ) blocking_host,  
    SUBSTRING(p. HOST, INSTR(p. HOST, ':') + 1) blocking_port,  
  
IF (p.COMMAND = 'Sleep', p.TIME, 0) idel_in_trx,  
 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  
INNER JOIN information_schema.INNODB_LOCKS l ON w.requested_lock_id = l.lock_id  
LEFT JOIN information_schema. PROCESSLIST p ON p.ID = b.trx_mysql_thread_id  
ORDER BY  
    wait_time DESC;


記得以前,當出現: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] : 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] : 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] : 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] : 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] : information_schema 13:38:31> select * from innodb_lock_waits \G
Empty set (0.00 sec)

[email protected] : 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)
複製程式碼





哈哈,有了以上這些資訊,以下問題就迎刃而解啦。當前有哪些事務在等待鎖? 這些鎖需要鎖哪些表,鎖哪些索引,鎖哪些記錄和值?處於等待狀態的相關SQL是什麼?在等待哪些事務完成 ?擁有當前鎖的SQL是什麼?

我想這些SQL對DBA來說不難吧?