2 回答

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

TA貢獻(xiàn)1860條經(jīng)驗(yàn) 獲得超9個(gè)贊
一種可能的解決方案是使用 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)注
- 262 瀏覽
添加回答
舉報(bào)