摘要:
死鎖:是指兩個或則多個事務在同一個資源上相互占用,並請求鎖定對方占用的資源,而導致惡性循環的現象;當產生死鎖的時候,MySQL會回滾一個小事務的SQL,確保另一個完成。上面是死鎖的概念,而在MySQL中innodb會出現死鎖的情況,但是查看死鎖卻很不“智能”。只能通過 show engine innodb status 查看,但只保留最后一個死鎖的信息,之前產生的死鎖都被刷掉了。下面介紹的工具卻很容易做到記錄。
前提:
下載地址:wget www.percona.com/downloads/percona-toolkit/2.2.2/percona-toolkit-2.2.2.tar.gz
安裝方法:perl Makefile.PL;make;make install
使用方法:
pt-deadlock-logger [OPTIONS] DSN
pt-deadlock-logger:顯示指定的DSN的死鎖日志信息,他能夠標准輸出到屏幕也可以把信息寫日志文件中(--log參數)甚至可以保留到指定的表中(--dest參數),該工具默認是永久執行,除非指定--run-time 或 --iterations 。
用法:
pt-deadlock-logger --ask-pass --run-time=10 --interval=3 --create-dest-table --dest D=test,t=deadlocks u=root,P=3306,h=192.168.200.25 Enter MySQL password:
參數:
--create-dest-table :創建指定的表。 --dest :創建存儲死鎖信息的表。 --database :-D,指定鏈接的數據庫。 --table :-t,指定存儲的表名。 --log :指定死鎖日志信息寫入到文件。 --run-time :運行次數,默認永久 --interval :運行間隔時間,默認30s。 u,p,h,P :鏈接數據庫的信息。
以上的參數,已經夠用,更多的參數信息見官網說明。
測試:
運行pt-deadlock-logger,操作數據庫:
session1:
root@localhost : test 04:46:11>select * from dead_tab; +----+------+------+---------+ | id | name | age | address | +----+------+------+---------+ | 1 | a | 33 | NULL | | 2 | bbb | 34 | NULL | | 3 | bbb | 35 | NULL | +----+------+------+---------+ 3 rows in set (0.00 sec) root@localhost : test 04:46:24>start transaction; Query OK, 0 rows affected (0.00 sec) root@localhost : test 04:46:31>update dead_tab set name ='A' where id >2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
section2:
root@localhost : test 04:46:13>start transaction; Query OK, 0 rows affected (0.01 sec) root@localhost : test 04:46:48>update dead_tab set name='AA' where id >1; ………… ………… 一直在等待着...
回到session1:
root@localhost : test 04:46:44>update dead_tab set name ='AA' where id >2; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction 死鎖出現了!
看pt-deadlock-logger的運行情況:
zhoujy@zhoujy:~$ pt-deadlock-logger --ask-pass --create-dest-table --dest D=test,t=deadlocks u=root,P=3306,h=192.168.200.25 Enter MySQL password: server ts thread txn_id txn_time user hostname ip db tbl idx lock_type lock_mode wait_hold victim query 192.168.200.25 2013-10-28T16:47:00 99 0 8 root localhost test dead_tab PRIMARY RECORD X w 0 update dead_tab set name='AA' where id >1 192.168.200.25 2013-10-28T16:47:00 100 0 16 root localhost test dead_tab PRIMARY RECORD X w 1 update dead_tab set name ='AA' where id >1
死鎖被打印出來,看看是否寫到表里:
root@localhost : test 04:32:45>select * from deadlocks\G; *************************** 1. row *************************** server: 192.168.200.25 ts: 2013-10-28 16:47:00 thread: 99 txn_id: 0 txn_time: 8 user: root hostname: localhost ip: db: test tbl: dead_tab idx: PRIMARY lock_type: RECORD lock_mode: X wait_hold: w victim: 0 query: update dead_tab set name='AA' where id >1 *************************** 2. row *************************** server: 192.168.200.25 ts: 2013-10-28 16:47:00 thread: 100 txn_id: 0 txn_time: 16 user: root hostname: localhost ip: db: test tbl: dead_tab idx: PRIMARY lock_type: RECORD lock_mode: X wait_hold: w victim: 1 query: update dead_tab set name ='AA' where id >1 2 rows in set (0.00 sec)
結果表明死鎖信息已經寫入到了表中,記錄的內容是2條產生的sql。繼續同樣的步驟再執行2次出現死鎖的SQL來驗證是之前的死鎖信息否被刷寫掉:
root@localhost : test 04:53:29>select count(*) from deadlocks; +----------+ | count(*) | +----------+ | 6 | +----------+ 1 row in set (0.02 sec)
繼續被寫入到表中。可以看到多個產生死鎖的sql,而不僅僅是最后一條產生死鎖的sql。
總結:
在檢查數據庫是死鎖信息的時候,又多了一個選擇。該工具也是通過show engine innodb status的信息來計算的。在mysql 5.6.2中,innodb_print_all_deadlocks這個設置可以看到死鎖的情況。