標籤:

關於高並發解決問題的一點總結

當項目中存在大量並發訪問數據時,因為事物之間是相互獨立的,所以會存在一個在更新數據的過程中(還沒有提交到資料庫),另一個進程已經在訪問,出現了數據不一致,這樣就會產生臟數據。

對於臟數據,公認的兩種解決辦法:悲觀鎖和樂觀鎖。

悲觀鎖是針對資料庫操作層面的枷鎖機制。總體來說就是針對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:資料庫 |