並發競態條件怎麼排查提示詞(超賣、重複扣款、餘額對不上、讀寫交錯)
出現庫存超賣、優惠券被領多次、餘額對不上、計數偏少這類「單個請求沒問題、並發時出錯」的情況時用:讓 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 | 讀到庫存 1 | 1 | |
| t2 | 讀到庫存 1 | 1 | |
| t3 | 判斷大於 0,寫入 0 | 0 | |
| 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()同款作品
用這條提示詞做出來的作品;原作者會因此獲得積分
還沒有同款,來做第一個。


0 條評論
還沒有評論,來搶沙發~