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 关注
- 267 浏览
添加回答
举报