什么場(chǎng)景會(huì)出現(xiàn)死鎖
兩個(gè)或者兩個(gè)以上的事務(wù)在執(zhí)行過(guò)程中,出現(xiàn)了因?yàn)闋?zhēng)奪資源造成的一種互相等待情況。
共享鎖死鎖的情況
| session1 | session2 |
|---|---|
| set autocommit =0; | set autocommit =0; |
| select * from edu_user lock in share mode; | select * from edu_user lock in share mode; |
| 阻塞:update edu_user set password="456789" where username = "王五"; | |
| 報(bào)錯(cuò):update edu_user set password="012345" where username = "王五"; | |
| 自動(dòng)結(jié)束當(dāng)前事務(wù):1213 - Deadlock found when trying to get lock; try restarting transaction | |
| commit; |
說(shuō)明:
session1和session2都開(kāi)啟事務(wù)后,都獲取了同一把共享鎖,但是session1寫操作需要對(duì)方阻塞,等待。session2寫操作同樣需要對(duì)方阻塞,等待。兩個(gè)都饑餓獲取不到鎖,產(chǎn)生了死鎖。
排他鎖死鎖的情況
| session1 | session2 |
|---|---|
| set autocommit =0; | |
| select * from edu_user where id = 1 for update; | set autocommit =0; |
| select * from edu_user where id = 2 for update; | |
| 阻塞等待:select * from edu_user where id = 2 for update; | |
| select * from edu_user where id = 1 for update; | |
| 1213 - Deadlock found when trying to get lock; try restarting transaction |
說(shuō)明:
session1和session都手動(dòng)提交事務(wù)時(shí),session1獲取了id為1的記錄的排他鎖,session2獲取了id為2的記錄的排他鎖。那么session1再想獲取id為2的排他鎖只能等待session2釋放鎖,session2再想獲取id為1的排他鎖只能等待session1釋放鎖。雙方都等待對(duì)方釋放鎖,那么就互相都饑餓,獲取不到鎖,產(chǎn)生了死鎖。
解決方法1,手動(dòng)整個(gè)事務(wù)回滾
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
解決方法2,設(shè)置超時(shí)回滾
# 說(shuō)明:事務(wù)等待行鎖定的時(shí)間,默認(rèn)值為50秒。發(fā)生鎖定等待超時(shí),將回滾當(dāng)前語(yǔ)句。
innodb_lock_wait_timeout
#說(shuō)明:InnoDB默認(rèn)情況下只會(huì)回滾事務(wù)超時(shí)的最后一個(gè)語(yǔ)句。指定這個(gè)參數(shù)將回滾整個(gè)事務(wù)。
innodb_rollback_on_timeout