为什么悲观的锁在PSQL中对我不起作用?该代码并非并发,我期望的是
我正在尝试获取和更新一列,并需要此过程以并发。因此,我通过选择更新
的选择行级锁仍然不符合预期。此列只是一个随机列,而不是主键或外键。
我将其更改为乐观的锁定,但它奏效了,但我试图理解为什么这不起作用。我在下面多次运行此代码,并且它的行为与单独运行的次数相同的次数并没有相同的方式。
_, err = s.xStore.ManageTransaction(func(ctx context.Context, tx *sqlx.Tx) (interface{}, error) {
_, err := tx.Exec("set transaction isolation level repeatable read")
if err != nil {
return nil, err
}
c, err = s.xStore.GetForUpdate(x)
//Some calculations
_ = s.xStore.Update(c)
return nil, nil
})
return
}()
}
这是我的获取查询,其中a for更新以锁定行。
func (s *xStore) GetForUpdate(id string) (*model.X, error) {
query := `
SELECT * FROM things where id = $1 FOR UPDATE`
_, err := s.db.Exec(query, id)
if err != nil {
return nil, err
}
var x model.X
err := s.db.Get(&x, query, id)
err = s.db.Get(&x, query, id)
if err != nil {
return nil, err
}
return &x, nil
}
I am trying to get and update a column and need this process to be concurrent. Therefore, I do a row level lock via SELECT FOR UPDATE
and then do my calculations and then do my update, all within a transaction with isolation level repeatable read
.However, this is still not concurrent as expected. This column is just a random column and not the primary or a foreign key.
I changed this to optimistic locking after and that worked but I am trying to understand why this did not work. I ran this code below concurrently multiple times and it did not behave the same way as it would have if I individually ran it the same number of times.
_, err = s.xStore.ManageTransaction(func(ctx context.Context, tx *sqlx.Tx) (interface{}, error) {
_, err := tx.Exec("set transaction isolation level repeatable read")
if err != nil {
return nil, err
}
c, err = s.xStore.GetForUpdate(x)
//Some calculations
_ = s.xStore.Update(c)
return nil, nil
})
return
}()
}
Here is my Get query with a FOR UPDATE to lock the row.
func (s *xStore) GetForUpdate(id string) (*model.X, error) {
query := `
SELECT * FROM things where id = $1 FOR UPDATE`
_, err := s.db.Exec(query, id)
if err != nil {
return nil, err
}
var x model.X
err := s.db.Get(&x, query, id)
err = s.db.Get(&x, query, id)
if err != nil {
return nil, err
}
return &x, nil
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的代码正在执行不同交易中的查询,
创建新的(db.begintx)或提供在某种程度上提供的使用,例如:
(请参阅 https://go.dev/doc/database/execute-execute-transactions )
Your code is executing queries in different transactions ,
create new one (db.BeginTx) or use provided someway like :
(Referring to https://go.dev/doc/database/execute-transactions )