查看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。
收集死鎖信息:
- 利用命令 SHOW ENGINE INNODB STATUS查看死鎖原因。
- 調試階段開啟 innodb_print_all_deadlocks,收集所有死鎖日志。
減少死鎖:
- 使用事務,不使用 lock tables 。
- 保證沒有長事務。
- 操作完之后立即提交事務,特別是在交互式命令行中。
- 如果在用 (SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE),嘗試降低隔離級別。
- 修改多個表或者多個行的時候,將修改的順序保持一致。
- 創(chuàng)建索引,可以使創(chuàng)建的鎖更少。
- 最好不要用 (SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE)。
- 如果上述都無法解決問題,那么嘗試使用 lock tables t1, t2, t3 鎖多張表
解決方法
首先先用sql查詢一下mysql的事務處理表
select * from information_schema.INNODB_TRX;
正常情況下的狀態(tài)都是RUNNING,但是在被鎖之后就會變成LOCK WAIT ,
一旦出現這種情況,就得殺死這個進程,如果進程殺不死就只能重啟Mysql服務了。
殺死進程
kill 進程ID