JAVA程序
JSTACK或者JVISUALVM都能自動檢查程序死鎖
數(shù)據(jù)庫命令
show engine innodb status
死鎖是指兩個或兩個以上的進程在執(zhí)行過程中贯要,因爭奪資源而造成的一種互相等待的現(xiàn)象。正常死鎖會自動釋放绽慈,innodb有一個內在的死鎖檢測工具盆佣,當死鎖超過一定時間后,會回滾其中一個事務陨舱,innodb_lock_wait_timeout可配置死鎖等待超時時間翠拣。
死鎖日志案例如下:
------------------------
LATEST DETECTED DEADLOCK
------------------------
111109 20:10:03
*** (1) TRANSACTION:
TRANSACTION 65839, ACTIVE 19 sec, OS thread id 4264 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 6 lock struct(s), heap size 1024, 3 row lock(s), undo log entries 1
MySQL thread id 3, query id 74 localhost 127.0.0.1 root Updating
UPDATE parent SET age=age+1 WHERE id=1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6833 page no 3 n bits 72 index `PRIMARY` of table
`test`.`parent` trx id 65839 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
*** (2) TRANSACTION:
TRANSACTION 65838, ACTIVE 26 sec, OS thread id 768 starting index read,
thread declared inside InnoDB 500
mysql tables in use 1, locked 1
7 lock struct(s), heap size 1024, 4 row lock(s), undo log entries 2
MySQL thread id 4, query id 75 localhost 127.0.0.1 root Updating
UPDATE parent SET age=age+1 WHERE id=2
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 6833 page no 3 n bits 72 index `PRIMARY` of table
`test`.`parent` trx id 65838 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6833 page no 3 n bits 72 index `PRIMARY` of table
`test`.`parent` trx id 65838 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
*** WE ROLL BACK TRANSACTION (1)
數(shù)據(jù)庫避免死鎖
- 合理的設計索引,區(qū)分度高的列放到組合索引前面游盲,使業(yè)務 SQL 盡可能通過索引定位更少的行误墓,減少鎖競爭。
- 調整業(yè)務邏輯 SQL 執(zhí)行順序益缎, 避免 update/delete 長時間持有鎖的 SQL 在事務前面谜慌。
- 避免大事務,盡量將大事務拆成多個小事務來處理莺奔,小事務發(fā)生鎖沖突的幾率也更小欣范。
- 以固定的順序訪問表和行。比如兩個更新數(shù)據(jù)的事務令哟,事務 A 更新數(shù)據(jù)的順序為 1恼琼,2;事務 B 更新數(shù)據(jù)的順序為 2,1屏富。這樣更可能會造成死鎖晴竞。
- 在并發(fā)比較高的系統(tǒng)中,不要顯式加鎖狠半,特別是是在事務里顯式加鎖噩死。如 select … for update 語句,如果是在事務里(運行了 start transaction 或設置了autocommit 等于0),那么就會鎖定所查找到的記錄神年。
- 盡量按主鍵/索引去查找記錄已维,范圍查找增加了鎖沖突的可能性,也不要利用數(shù)據(jù)庫做一些額外額度計算工作已日。比如有的程序會用到 “select … where … order by rand();”這樣的語句衣摩,由于類似這樣的語句用不到索引,因此將導致整個表的數(shù)據(jù)都被鎖住捂敌。
- 優(yōu)化 SQL 和表設計艾扮,減少同時占用太多資源的情況。比如說占婉,減少連接的表泡嘴,將復雜 SQL 分解為多個簡單的 SQL。