2 回答

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

TA貢獻1860條經(jīng)驗 獲得超9個贊
一種可能的解決方案是使用 GORM 事務(wù)(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 關(guān)注
- 236 瀏覽
添加回答
舉報