在數(shù)據(jù)庫(kù)高并發(fā)場(chǎng)景下,死鎖大家或多或少都遇到過(guò),但是很多時(shí)候沒(méi)有很重視,通過(guò)各種奇奇怪怪的方法避免了。最近使用Spark更新數(shù)據(jù)導(dǎo)致一次死鎖,特意學(xué)習(xí)一下鎖的問(wèn)題。
1. 鎖分類體系
MySQL鎖可從多個(gè)維度進(jìn)行分類:
按粒度:全局鎖、表級(jí)鎖、頁(yè)級(jí)鎖、行級(jí)鎖
按屬性:共享鎖(S鎖)、排他鎖(X鎖)
按狀態(tài):意向鎖(IS/IX鎖)
按算法:記錄鎖、間隙鎖、臨鍵鎖
按并發(fā)策略:樂(lè)觀鎖、悲觀鎖
2. 主要的鎖
全局鎖:主要用于全庫(kù)邏輯備份場(chǎng)景,通過(guò)鎖定整個(gè)數(shù)據(jù)庫(kù)確保備份數(shù)據(jù)的一致性
表級(jí)鎖:可通過(guò)命令顯式加鎖,或隱式通過(guò)元數(shù)據(jù)鎖(MDL)實(shí)現(xiàn),常見于DDL操作或低并發(fā)查詢場(chǎng)景,通過(guò)鎖定整張表維護(hù)數(shù)據(jù)完整性
行級(jí)鎖:通過(guò)索引對(duì)特定數(shù)據(jù)行進(jìn)行加鎖(記錄鎖/間隙鎖/臨鍵鎖),特別適用于高并發(fā)OLTP系統(tǒng),通過(guò)細(xì)粒度鎖控制提升并發(fā)性能
樂(lè)觀鎖:基于數(shù)據(jù)版本號(hào)(Version)機(jī)制實(shí)現(xiàn),在讀多寫少場(chǎng)景中,通過(guò)版本號(hào)控制實(shí)現(xiàn)樂(lè)觀并發(fā)控制,避免鎖競(jìng)爭(zhēng)
悲觀鎖:悲觀鎖是由數(shù)據(jù)庫(kù)自己實(shí)現(xiàn)了的,在寫操作頻繁場(chǎng)景中,通過(guò)鎖定資源防止并發(fā)沖突,確保數(shù)據(jù)一致性
3. 出現(xiàn)鎖的場(chǎng)景
在使用spark更新數(shù)據(jù)的時(shí)候,發(fā)現(xiàn)任務(wù)有報(bào)錯(cuò),報(bào)錯(cuò)消息是鎖相關(guān)的,特意留意了一下,大體意思是觸發(fā)了寫鎖,有一個(gè)task在寫數(shù)據(jù)的時(shí)候數(shù)據(jù)庫(kù)報(bào)錯(cuò)無(wú)法寫入。
出現(xiàn)的原因:因?yàn)閟park的task是并發(fā)執(zhí)行的,任務(wù)有多個(gè)并行度的情況下,寫入的task也是并發(fā)執(zhí)行的,意思就是同時(shí)又很多個(gè)寫入的事務(wù),而且寫入的操作是批量寫入,手動(dòng)提交事務(wù),這就導(dǎo)致了有task任務(wù)提交的時(shí)候剛好有其他的task在操作同一條數(shù)據(jù)。
解決方案:最簡(jiǎn)單的解決方案就是將spark中的操作數(shù)據(jù)庫(kù)前的結(jié)果mappartitions為一個(gè),避免并發(fā)更新;另外一種方案就是單條數(shù)據(jù)更新,自動(dòng)提交事務(wù),這種情況下基本很難遇到鎖
最后還需要注意,更新語(yǔ)句的條件中的字段一定要有索引,否則全表掃描是很慢的。





暫無(wú)評(píng)論,快來(lái)評(píng)論吧!