为什么悲观锁定在 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

(参考https://go.dev/doc/database/execute-transactions