數據庫高併發下樂觀鎖的原理

 在高併發下,常常須要處理SELECT以後,在業務層處理邏輯,再執行UPDATE的狀況。html

  若兩個鏈接併發查詢同一條數據,而後在執行一些邏輯判斷或業務操做後,執行UPDATE,可能出現與預期不相符的結果。sql

  在不使用悲觀鎖與複雜SQL的前提下,可使用樂觀鎖處理該問題,同時兼顧性能。數據庫

 

  場景模擬:併發

  假設一張表兩個字段,一個id,一個use_count。表裏存了100個id,每一個id對應本身的use_count。高併發

  當id每使用一次,use_count要加1。當use_count大於1000時,這個id就不能在被使用了(換句話說 沒法從數據庫中查出)。post

  在高併發狀況下,會遇到一種問題:假設數據表中有一條記錄爲:id=123456, use_count=999  A與B兩個鏈接併發查詢這個id=123456,都執行下列SQL:性能

1
SELECT  FROM  table  WHERE  id=123456  and  use_count < 1000;

  A先執行,獲得id=123456的use_count是999,以後在程序裏作了一些邏輯判斷或業務操做後執行SQL:spa

1
UPDATE  table  SET  use_count + 1  WHERE  id=123456;

  在A作判斷且沒有update以前,B也執行了查詢SQL,發現use_count是999,以後它也會執行SQL:code

1
UPDATE  table  SET  use_count + 1  WHERE  id=123456;

  可是,事實上B不該該取得這個id,由於A已是第1000個使用者。htm

  處理步驟以下:

  一、添加第3個字段version,int類型,default值爲0。version值每次update時做加1處理。

1
ALTER  TABLE  table  ADD  COLUMN  version  INT  DEFAULT  '0'  NOT  NULL  AFTER  use_count;

  二、SELECT時同時獲取version值(例如爲3)。

1
SELECT  use_count, version  FROM  table  WHERE  id=123456  AND  use_count < 1000;

  三、UPDATE時檢查version值是否爲第2步獲取到的值。

1
UPDATE  table  SET  version=4, use_count=use_count+1  WHERE  id=123456  AND  version=3;

  若是UPDATE的記錄數爲1,則表示成功。若是UPDATE的記錄數爲0,則表示已經被其餘鏈接UPDATE過了,需做異常處理

 

參考地址:http://latrell.me/post-358.html

相關文章
相關標籤/搜索