App下載

mysql數據庫死鎖:Deadlock found when trying to get lock; try restarting transaction

不許揪我的小耳朵 2021-08-26 17:06:47 瀏覽數 (10827)
反饋

查看mysql死鎖日志

show engine innodb status

找到信息中LATEST DETECTED DEADLOCK這一行,可以看到mysql的死鎖信息詳情

------------------------
LATEST DETECTED DEADLOCK
------------------------
2021-08-25 14:13:37 0x7facac6b8700
*** (1) TRANSACTION:
TRANSACTION 1589867098, ACTIVE 0 sec fetching rows
mysql tables in use 3, locked 3
LOCK WAIT 508 lock struct(s), heap size 57552, 4 row lock(s)
MySQL thread id 201608808, OS thread handle 140379228206848, query id 3088485657 172.18.119.16 root updating
UPDATE web_viewlog SET viewcount=viewcount+1,lasttime='2021-08-25 14:13:37' WHERE uid=2150174 and kename='21es1mmi'
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 564 page no 16179 n bits 208 index PRIMARY of table `w3cschool`.`web_viewlog` trx id 1589867098 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 16; compact format; info bits 0


MySQL有三種鎖的級別:頁級、表級、行級。

表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。

行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。

頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。


行級鎖

行級鎖在使用的時候并不是直接鎖掉這行記錄,而是鎖索引
如果一條sql用到了主鍵索引(mysql主鍵自帶索引),mysql會鎖住主鍵索引;
如果一條sql操作了非主鍵索引,mysql會先鎖住非主鍵索引,再鎖定主鍵索引.


什么情況下會造成死鎖

所謂死鎖<DeadLock>: 是指兩個或兩個以上的進程在執(zhí)行過程中,
因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。
此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產生了死鎖,這些永遠在互相等竺的進程稱為死鎖進程。
表級鎖不會產生死鎖.所以解決死鎖主要還是針對于最常用的InnoDB


收集死鎖信息:

  1. 利用命令 SHOW ENGINE INNODB STATUS查看死鎖原因。
  2. 調試階段開啟 innodb_print_all_deadlocks,收集所有死鎖日志。

減少死鎖:

  1. 使用事務,不使用 lock tables 。
  2. 保證沒有長事務。
  3. 操作完之后立即提交事務,特別是在交互式命令行中。
  4. 如果在用 (SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE),嘗試降低隔離級別。
  5. 修改多個表或者多個行的時候,將修改的順序保持一致。
  6. 創(chuàng)建索引,可以使創(chuàng)建的鎖更少。
  7. 最好不要用 (SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE)。
  8. 如果上述都無法解決問題,那么嘗試使用 lock tables t1, t2, t3 鎖多張表

 

解決方法

首先先用sql查詢一下mysql的事務處理表

select * from information_schema.INNODB_TRX;



正常情況下的狀態(tài)都是RUNNING,但是在被鎖之后就會變成LOCK WAIT ,

一旦出現這種情況,就得殺死這個進程,如果進程殺不死就只能重啟Mysql服務了。


殺死進程

kill 進程ID


0 人點贊