2 回答

TA貢獻1816條經驗 獲得超6個贊
如果要使用基本的 ORM 功能,可以在檢索記錄時使用FOR UPDATE
查詢選項,數據庫將鎖定該特定連接的記錄,直到該連接發出UPDATE
查詢以更改該記錄。
SELECT
和UPDATE
語句必須發生在同一個連接上,這意味著您需要將它們包裝在一個事務中(否則 Go 可能會通過不同的連接發送第二個查詢)。
請注意,這將使所有其他想要SELECT
相同記錄的連接等到您完成UPDATE
. 對于大多數應用程序來說,這不是問題,但如果您的并發性非常高,或者兩者之間的時間SELECT ... FOR UPDATE
很UPDATE
長,那么這可能不適合您。
除了 之外FOR UPDATE
,該FOR SHARE
選項聽起來也可以為您工作,鎖定爭用較少(但我不太清楚,不能肯定地說)。
注意:這假設您使用支持的 RDBMS SELECT ... FOR UPDATE
; 如果沒有,請更新問題以告訴我們您正在使用哪個 RDBMS。
另一種選擇是繞過 ORM 并執行db.Exec("UPDATE counter_table SET counter = counter + 1 WHERE id = ?", 42)

TA貢獻1860條經驗 獲得超9個贊
一種可能的解決方案是使用 GORM 事務(https://gorm.io/docs/transactions.html)。
err := db.Transaction(func(tx *gorm.DB) error {
// Get model if exist
var feature models.Feature
if err := tx.Where("id = ?", c.Param("id")).First(&feature).Error; err != nil {
return err
}
// Increment Counter
if err := tx.Model(&feature).Update("Counter", feature.Counter+1).Error; err != nil {
return err
}
return nil
})
if err != nil {
c.Status(http.StatusInternalServerError)
return
}
c.Status(http.StatusOK)
- 2 回答
- 0 關注
- 241 瀏覽
添加回答
舉報