關於高並發解決問題的一點總結
當項目中存在大量並發訪問數據時,因為事物之間是相互獨立的,所以會存在一個在更新數據的過程中(還沒有提交到資料庫),另一個進程已經在訪問,出現了數據不一致,這樣就會產生臟數據。
對於臟數據,公認的兩種解決辦法:悲觀鎖和樂觀鎖。
悲觀鎖是針對資料庫操作層面的枷鎖機制。總體來說就是針對sql上鎖,例如
select *from A a where a.id=1 for update;
像上面的sql就是給查詢的那條數據上鎖了,防止自己查詢別人去更新這條數據。需要注意的是上鎖的欄位必須是有索引的欄位,因為枷鎖是在索引的基礎上的,不然會鎖了整個表。for update 後面還可以加欄位或者枷鎖時間等。以上就是悲觀鎖,缺點就是增加資料庫的開銷,存在等待問題,而且並發高的話,資料庫是承受不住的會出現死鎖。
樂觀鎖是使用邏輯層來解決問題,一般是在表中添加一個防止並發讀取更新的欄位,主要有Version和timestamp,當操作數據時給Version+1例如:當需要修改一條數據時可以判斷一下Version是否>表中現在表中的Version,不大於事物回滾,並且走入異常,獲取異常再去做後續處理,同樣樂觀鎖也有缺陷,自己系統有了完美的枷鎖機制,但是表被其他系統修改就沒辦法了。
一般情況樂觀鎖和悲觀鎖是配合使用,本人更傾向於將樂觀鎖寫進存儲過程,這樣操作表的時候使用存儲過程,有了一個公共的約定。
create or replace procedure test("version" int,"varid" int ) as declare varVersion int;beginselect version into varVersion from A a where a.id=varid;set varVersion = varVersion+1;update A a set a.id=2,a.version=varVersion where a.version=version;end
結尾提一句:線程同步synchornized也是變相的加了一個悲觀鎖,所以慎用。
推薦閱讀:
※資料庫面試題(開發者必看)
※資料庫原理
※劉寅:TiDB 工具鏈和生態
※OceanBase:當金融擁抱科技
※如何理解並正確使用MySql索引
TAG:資料庫 |