1. 程式人生 > >MySQL InnoDB下的死鎖和鎖等待超時的問題驗證與梳理

MySQL InnoDB下的死鎖和鎖等待超時的問題驗證與梳理

MySQL資料庫死鎖問題 例子表
user{
id 主鍵
name
}


//PART01
備註:共享鎖之間可以併發執行,排他鎖需要等待其他共享鎖、排他鎖釋放
共享鎖(簡單的select語句不會加鎖)
select * from user where id='5' lock in share mode;
排他鎖
update user set name='111' where id='5';


//PART02
表級鎖(非索引作為條件)
update user set name='222' where name='111'
行級鎖(索引作為條件)
update user set name='111' where id='5'


//PART03

備註:完整的事務命令
mysql>begin;
mysql>update user set name='111' where id='5';
mysql>commit;

問題:
鎖等待超時Lock wait timeout exceeded;
事務1
mysql>begin;
mysql>update user set name='111' where id='5';//事務1佔著本行行級鎖,一直不執行commit,不釋放行級鎖
mysql>
事務2
mysql>begin;
mysql>update user set name='222' where id='5';//卡住了,等待事務1 commit後釋放行級鎖,直到超時



死鎖Deadlock found when trying to get lock;
事務1
mysql>begin;
mysql>update user set name='111' where id='5';//事務1佔有本行行級鎖
mysql>update user set name='222' where name='111';//卡住了,事務1佔有表級鎖時候,需要等待事務2釋放行級鎖,進入 A等待B,B又等待A的死鎖(此時mysql的內部機制會重啟事務2,解決死鎖問題,保證事務1可以正常進行)
事務2
mysql>begin;
mysql>update user set name='333' where id='5';//事務2要佔有行級鎖時卡住了,排隊等待事務1釋放本行行級鎖(驗證過,多個事務是有等待順序的)


注,驗證發現

行級鎖如果確定的行不同,不會等待對方,例如where id=1 和 where id=2不會讓對方等待,只有同時where =1時,後開始的事務才會等待先開始的事務釋放行級鎖;

表級鎖則始終要後事務要等待前一個事務釋放表級鎖,不論條件是where name='11'和where name='22',還是where name='11'和where name='11'