如果行更改,如何回滚事务?

use*_*521 3 postgresql postgresql-9.3

我正在使用Postgres 9.3.

当我更新表中的行时,我的流程如下所示:

  1. 获取旧行(例如SELECT * FROM tbl WHERE id = 1
  2. 在旧数据范围内验证新数据(在第 1 点中提取的旧行) - 这是由我的应用程序在 postgres 之外完成的。
  3. 用新数据更新行(例如UPDATE tbl SET .... WHERE id = 1

问题是old数据可能在第 2 点期间发生变化,因此验证,即使通过也可能是outdated在第 3 点(更新行)期间。我知道我可以执行这样的更新UPDATE .... WHERE id = 1 AND column1='oldValue'以确保某些字段不会更改,但是我的验证(也比较新旧值)非常复杂,我无法在 SQL UPDATE 语句中“编写”它。

所以我想到了这样的事情:

  1. BEGIN
  2. SELECT * FROM tbl WHERE id = 1
  3. 在我这边执行验证
  4. UPDATE SET=... WHERE id = 1
  5. COMMIT

COMMIT如果在事务执行期间 id = 1 的行发生更改,我想失败。是否可以使用这样的交易?如果不是,其他解决方案是什么?

Len*_*art 6

不确定为什么不直接在 where 子句中使用附加谓词进行更新,但如果不可能,您可以选择更新,如下所示:

SELECT * FROM tbl WHERE id = 1 FOR UPDATE
Run Code Online (Sandbox Code Playgroud)

这将锁定所选行并防止在您进行验证时对其进行更新。