【发布时间】:2021-05-24 17:17:15
【问题描述】:
我正在开发一个系统,以启用具有递增队列编号的患者登记。我正在使用 Go、GORM 和 MySQL。
当多个患者同时注册时会出现问题,他们往往会获得相同的队列号,这是不应该发生的。
我尝试使用事务和挂钩来实现这一点,但我仍然得到重复的队列号。我还没有找到任何关于如何在事务发生时锁定数据库的资源。
func (r repository) CreatePatient(pat *model.Patient) error {
tx := r.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
err := tx.Error
if err != nil {
return err
}
// 1. get latest queue number and assign it to patient object
var queueNum int64
err = tx.Model(&model.Patient{}).Where("registration_id", pat.RegistrationID).Select("queue_number").Order("created_at desc").First(&queueNum).Error
if err != nil && err != gorm.ErrRecordNotFound {
tx.Rollback()
return err
}
pat.QueueNumber = queueNum + 1
// 2. write patient data into the db
err = tx.Create(pat).Error
if err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
【问题讨论】:
-
由于竞争条件,您不能安全地查找数据库中的最高 id 编号然后将其加一。交易没有帮助。当你在数据库中插入一行时,你会得到它的 ID 号。看看这个。 stackoverflow.com/questions/28773963/…
-
很好的输入琼斯。但问题是我们使用 UUID 作为主键。即使我们使用增量主键,我们也不能依赖它来分配队列号,因为在一个表中有来自不同注册的患者。我们不希望患者根据不同登记的最后一个队列号来获取队列号。
标签: mysql go transactions locking go-gorm