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

 在高併發下,經常需要處理SELECT之後,在業務層處理邏輯,再執行UPDATE的情況。

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

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

 

  場景模擬:

  假設一張表兩個字段,一個id,一個use_count。表裏存了100個id,每個id對應自己的use_count。

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

  在高併發情況下,會遇到一種問題:假設數據表中有一條記錄爲: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:

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

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

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

  但是,事實上B不應該取得這個id,因爲A已經是第1000個使用者。

  處理步驟如下:

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

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

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

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

  3、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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章