並發競態條件怎麼排查提示詞(超賣、重複扣款、餘額對不上、讀寫交錯)

出現庫存超賣、優惠券被領多次、餘額對不上、計數偏少這類「單個請求沒問題、並發時出錯」的情況時用:讓 AI 找出「先讀後寫」的競態窗口,畫出兩個請求交錯的時序,給出數據庫層或代碼層的正確修復。

NNathaniel bigo··原創首發·AI 輔助撰寫
通用大模型 對話模型通用
你是一名精通並發與數據庫事務的後端工程師。下面的代碼在並發場景下出現了數據錯誤,請找出競態條件並修復。

資訊:
- 語言、框架、數據庫:[語言、框架、數據庫](例:Python + Django + MySQL 8)
- 部署方式:[單實例/多實例/多進程]
- 出錯現象:[如庫存變成負數、同一張券被領兩次]
- 數據庫隔離級別(不知道就寫預設):[隔離級別]
- 相關代碼(包括事務邊界):
  [粘貼代碼]

請按以下步驟分析:
1. 標出所有「讀取 → 判斷 → 寫入」的位置,這是競態最常出現的地方。
2. 用時序表演示兩個並發請求如何交錯導致錯誤:時刻 | 請求 A | 請求 B | 數據庫中的值。
3. 說明現有的保護為什麼不夠,例如:事務只能保證原子提交,不能阻止兩個事務讀到同一個舊值;進程內的鎖在多實例部署下無效;當前隔離級別下會發生什麼。
4. 給出修復方案,按推薦程度排序,每種寫清適用條件和代價:
   - 條件更新:把判斷放進寫語句裏,檢查受影響行數;
   - 悲觀鎖:SELECT ... FOR UPDATE,注意鎖的範圍和死鎖;
   - 樂觀鎖:版本號字段 + 衝突重試;
   - 唯一約束:用數據庫約束兜底防重複;
   - 分佈式鎖:只在前面幾種都不適用時使用,說明過期時間和釋放時的注意事項。
5. 寫出推薦方案的完整代碼。
6. 寫一個能復現問題的並發測試(例如同時發起 50 個請求),修復前應失敗,修復後應通過。

如果資訊不足以判斷(比如不清楚是否多實例部署),先指出需要確認什麼。

高亮處換成你自己的內容:[語言、框架、數據庫]、[單實例/多實例/多進程]、[如庫存變成負數、同一張券被領兩次]、[隔離級別]、[粘貼代碼]

ChatGPT Plus 充值

已被複製 0 次

使用說明

怎麼填變量:[部署方式] 一定要寫,很多人用語言自帶的鎖(比如 Java 的 synchronized、Python 的 threading.Lock)解決了單機測試,上線多實例後照樣出錯。事務邊界要貼清楚,代碼裏哪一段在事務內、哪一段在事務外直接影響結論。

常見坑:

  • 「我已經加了事務」是最常見的誤解。預設隔離級別下,兩個事務完全可以讀到同一個庫存值,然後各自減 1。
  • 能用一條帶條件的 UPDATE 解決的,就不要上分佈式鎖。條件更新簡單、可靠、沒有鎖過期的問題。
  • 並發測試要真正並發:用線程池或異步同時發起請求,而不是循環裏一個接一個地調用。

追問技巧:修復後追問「在這個方案下,如果數據庫主從延遲、或者請求在提交前超時重試,還會出錯嗎」,把邊界情況也問到。

示例輸出

示例,僅供參考(庫存超賣)
時刻請求 A請求 B庫存
t1讀到庫存 11
t2讀到庫存 11
t3判斷大於 0,寫入 00
t4判斷大於 0,寫入 0(應拒絕)0,賣出 2 件

推薦修復:把判斷放進 UPDATE,並檢查受影響行數。

python
from django.db.models import F

updated = Product.objects.filter(id=pid, stock__gte=qty).update(stock=F("stock") - qty)
if updated == 0:
    raise OutOfStock()

同款作品

用這條提示詞做出來的作品;原作者會因此獲得積分

做同款

還沒有同款,來做第一個。

Nathaniel 的更多內容

同主題

同模型

0 條評論

登入 後參與評論

還沒有評論,來搶沙發~