django select_for_update

select_for_update
為了演示常見的并發(fā)問題,我們將使用銀行賬戶模型,開始我們?yōu)閹魧?shí)例提供一個(gè)簡(jiǎn)單的存款和撤銷方法:
當(dāng)兩個(gè)用戶同時(shí)在同一個(gè)帳戶上執(zhí)行操作時(shí)會(huì)發(fā)生什么?

1、用戶A提取帳戶 - 余額為100$。
2、用戶B提取帳戶 - 余額為100$。
3、用戶B退出30$ - 余額更新為100$ - 30$ = 70$。
4、用戶A存款50$ - 余額更新為100$ + 50$ = 150$。

這里發(fā)生了什么?用戶B要求提取30$,用戶A存入50$ - 我們預(yù)期余額為120$,但最終為150$。

為什么會(huì)這樣呢?
在步驟4,當(dāng)用戶A更新余額時(shí),他在存儲(chǔ)器中存儲(chǔ)的金額已經(jīng)過時(shí)(用戶B已經(jīng)退出30$)。

為了防止這種情況發(fā)生,我們需要確保我們正在處理的資源在我們正在計(jì)算的過程中不會(huì)改變。

悲觀的做法表明,您應(yīng)該完全鎖定資源,直到完成它 。 如果沒有人可以在您處理對(duì)象時(shí)獲取對(duì)象上的鎖定,那么可以確保對(duì)象沒有被更改。

我們使用數(shù)據(jù)庫鎖有幾個(gè)原因:
1、 數(shù)據(jù)庫非常擅長(zhǎng)管理鎖并保持一致性。
2、數(shù)據(jù)庫是訪問數(shù)據(jù)的最低級(jí)別 - 獲取最低級(jí)別的鎖也會(huì)防止其他進(jìn)程嘗試修改數(shù)據(jù)。 例如,DB中的直接更新,cron作業(yè),清理任務(wù)等。
3、Django應(yīng)用程序可以在多個(gè)進(jìn)程 (例如工作者)上運(yùn)行。 在應(yīng)用程序級(jí)別維護(hù)鎖將需要大量(不必要的)工作。

要在Django中鎖定一個(gè)對(duì)象,我們使用select_for_update 。

1、我們?cè)谖覀兊牟樵兤魃鲜褂胹elect_for_update來告訴數(shù)據(jù)庫鎖定對(duì)象,直到事務(wù)完成。
2、在數(shù)據(jù)庫中鎖定一行需要一個(gè)數(shù)據(jù)庫事務(wù) - 我們使用Django的裝飾器transaction.atomic來定義事務(wù)。
3、我們使用類方法而不是實(shí)例方法 - 我們告訴數(shù)據(jù)庫要上鎖,然后它會(huì)返回鎖的對(duì)象給我們。 為了實(shí)現(xiàn)這一點(diǎn),我們需要從數(shù)據(jù)庫中獲取對(duì)象。 如果我們使用self,那么就是在操作一個(gè)已經(jīng)從數(shù)據(jù)庫中獲取出來的對(duì)象,這個(gè)對(duì)象無法保證自己是沒有被上鎖的。
4、帳戶中的所有操作都在數(shù)據(jù)庫事務(wù)中執(zhí)行。
讓我們看看如何通過我們的新方法來阻止前面說的情況:
1、用戶A要求退出30$:
用戶A獲取帳戶上的鎖。
余額為100美元。
2、用戶B要求存入50$:
嘗試獲取鎖定帳戶失?。ㄓ捎脩鬉鎖定)。
用戶B等待鎖釋放 。
3、用戶A撤回30$:
余額是70$。
帳戶上的用戶A的鎖定被釋放 。
4、用戶B獲取帳戶上的鎖。
余額是70$。
新余額為70 + 50 = 120$。

5、賬號(hào)上用戶B的鎖定被釋放,余額為120$。Bug消失了!

這里你需要了解select_for_update

1、在我們的方案中,用戶B等待用戶A釋放鎖,我們可以告訴Django 不要等待鎖釋放并引發(fā)DatabaseError。 為此,我們可以將select_for_update的nowait參數(shù)設(shè)置為True, …select_for_update(nowait=True) 。

2、選擇相關(guān)對(duì)象也被鎖定 -當(dāng)使用select_for_update與select_related時(shí),相關(guān)對(duì)象也被鎖定。

例如,如果我們選擇與用戶一起select_related帳戶,用戶和帳戶將被鎖定。 如果在存款期間,例如有人正在嘗試更新名字,該更新將失敗,因?yàn)橛脩魧?duì)象被鎖定。

如果您正在使用PostgreSQL或Oracle,這可能不是一個(gè)問題,由于即將到來的Django 2.0 的新功能 。 在此版本中,select_for_update具有“of”選項(xiàng),用于顯式地聲明要鎖定查詢中的哪些表 。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在數(shù)據(jù)系統(tǒng)的殘酷現(xiàn)實(shí)中,很多事情都可能出錯(cuò): 數(shù)據(jù)庫軟件、硬件可能在任意時(shí)刻發(fā)生故障(包括寫操作進(jìn)行到一半時(shí))。 ...
    冰菓_閱讀 672評(píng)論 0 1
  • 上期我們講到LoadRunner性能測(cè)SQL server等待類型,這期我們講LoadRunner性能測(cè)試如何跟蹤...
    82a7fe2508f4閱讀 296評(píng)論 0 0
  • 一、數(shù)據(jù)庫中的鎖 在數(shù)據(jù)庫中l(wèi)ock和latch都可以被稱為“鎖”。它們鎖的對(duì)象不一樣。latch是用來保證并發(fā)線...
    鐘離惜閱讀 310評(píng)論 0 0
  • 數(shù)據(jù)庫的鎖機(jī)制 并發(fā)控制 在計(jì)算機(jī)科學(xué),特別是程序設(shè)計(jì)、操作系統(tǒng)、多處理機(jī)和數(shù)據(jù)庫等領(lǐng)域,并發(fā)控制(Concurr...
    夢(mèng)醒家先生閱讀 588評(píng)論 0 1
  • 支付操作出現(xiàn)的問題與解決方法 場(chǎng)景介紹 存在的問題 解決方法代碼級(jí)別加鎖數(shù)據(jù)庫級(jí)加鎖悲觀鎖樂觀鎖 最終結(jié)果 場(chǎng)景介...
    L_Y_CHENG閱讀 2,447評(píng)論 2 1

友情鏈接更多精彩內(nèi)容