先放個網(wǎng)絡(luò)美女提提神

MySQL的行級鎖是由各個引擎自己實現(xiàn)的,innodb支持行級鎖但MyISAM卻不支持,這也是innodb更受青睞的原因之一。
想要高效使用innodb的行級鎖,必須要熟悉兩階段鎖協(xié)議和死鎖預(yù)防。
兩階段鎖協(xié)議
-
定義
事務(wù)執(zhí)行時,在運(yùn)行到需要加鎖的語句時加鎖,但不是對應(yīng)語句執(zhí)行完了就釋放鎖,而是等到commit時才會釋放鎖。
圖1 兩階段鎖協(xié)議實例
如圖1所示,session1在t1時刻對id=1的行加鎖了。在t4時刻session2想要更新id=1的行,這是會被阻塞,因為id=1的行鎖需要等到t5時刻session1 commit后才會被釋放。
對程序的影響
在編寫程序時,程序員應(yīng)當(dāng)盡量將需要請求行鎖的代碼放到離commit更近的地方。
死鎖預(yù)防措施
-
我們知道死鎖發(fā)生的條件
- 多個資源互斥訪問
- 資源被獲取后不可搶占
- 多個線程循環(huán)等待
-
在數(shù)據(jù)庫行級鎖場景下,這些條件都會被滿足,因此對于行級鎖的請求肯定會造成死鎖。那我們應(yīng)當(dāng)如何解決死鎖呢,有如下兩種辦法:
死鎖檢測
著名的死鎖檢測方法就是銀行家算法,不知道的小伙伴可以查一下。但這有個非常大的缺點(diǎn),每次死鎖檢測的時間復(fù)雜度為O(N),因此如果有1000個線程要執(zhí)行加鎖操作時就會帶來100萬級別的時間復(fù)雜度開銷。控制并發(fā)度
很好理解,線程數(shù)越少死鎖發(fā)生的概率越小。可以通過控制統(tǒng)一時刻訪問同一行的請求數(shù)量來控制并發(fā)度以減少死鎖發(fā)生的概率。另一種方式就是將數(shù)據(jù)分散,比如數(shù)據(jù)庫中原來有一行數(shù)據(jù)記錄用戶在銀行的存款數(shù)額,現(xiàn)在將其拆分成10行,10行數(shù)額的相加就是這個用戶的存款數(shù),當(dāng)一個請求要修改該用戶的存款數(shù)額的時候,就隨機(jī)從10行中選一行進(jìn)行操作,這樣就將并發(fā)度減少為了1/10。
