为什么悲观锁定在 psql 中对我不起作用?代码不像我期望的那样是并发的
Why is pessimistic locking not working for me in psql? The code is not concurrent as I would expect it to be
我正在尝试获取和更新列并且需要此过程是并发的。因此,我通过 SELECT FOR UPDATE
进行行级锁定,然后进行计算,然后进行更新,所有这些都在具有隔离级别 repeatable read
的 t运行saction 中进行。但是,这仍然不是并发的正如预期的那样。此列只是一个 运行dom 列,而不是主键或外键。
之后我将其更改为乐观锁定并且有效,但我试图理解为什么这不起作用。我 运行 下面的这段代码并发多次,它的行为方式与我单独 运行 相同次数时的行为方式不同。
_, 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
}()
}
这是我使用 FOR UPDATE 锁定行的 Get 查询。
func (s *xStore) GetForUpdate(id string) (*model.X, error) {
query := `
SELECT * FROM things where id = 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
}
您的代码正在不同事务中执行查询,
创建一个新的 (db.BeginTx) 或使用提供的方式,例如:
- 行 := tx.Query(你的查询)
- 做一些计算
- tx.ExecContext
- tx.Commit
我正在尝试获取和更新列并且需要此过程是并发的。因此,我通过 SELECT FOR UPDATE
进行行级锁定,然后进行计算,然后进行更新,所有这些都在具有隔离级别 repeatable read
的 t运行saction 中进行。但是,这仍然不是并发的正如预期的那样。此列只是一个 运行dom 列,而不是主键或外键。
之后我将其更改为乐观锁定并且有效,但我试图理解为什么这不起作用。我 运行 下面的这段代码并发多次,它的行为方式与我单独 运行 相同次数时的行为方式不同。
_, 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
}()
}
这是我使用 FOR UPDATE 锁定行的 Get 查询。
func (s *xStore) GetForUpdate(id string) (*model.X, error) {
query := `
SELECT * FROM things where id = 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
}
您的代码正在不同事务中执行查询, 创建一个新的 (db.BeginTx) 或使用提供的方式,例如:
- 行 := tx.Query(你的查询)
- 做一些计算
- tx.ExecContext
- tx.Commit