数据库:在事务内部获取更新后执行更新查询

时间:2015-06-18 13:58:24

标签: sql database transactions ibm-db2

我正在研究IBM DB,但我认为这些概念几乎相同。

我想获取一行,返回这些数据(或者将它们保存到变量中)并更新该特定行的某些字段。可能有许多实例尝试同时执行该查询,因此我们需要获取原子操作。

每行都有一个名为pending的字段,init为FALSE。当一个实例获取此行时,将其设置为TRUE(这是我想要执行的更新)。我需要它的原因也是原子的,是我的查询获取表的第一行,其中pending为FALSE。

在伪代码中我有这样的东西:

OPEN_DB(myDb, "DBNAME");  // opening the DB
BEGIN_TRANSACTION(myDb);  // beginning transaction on my db
EXECUTE_QUERY(myDb,"SELECT * FROM tbname WHERE pending == 0 ORDER BY colid LIMIT 1");
... assign a cursor to my results
while (valid_data) {
    // assign column fields to variable

    // and here i want to do the update for this column
    // I guess the problem is here
     EXECUTE_QUERY(myDb,"UPDATE tbname SET pending = 1 WHERE colid=@colid")

}
COMMIT();

不要担心语法,它们是宏,只要它们自己执行就可以工作。我猜这个问题出在第二个查询上,但为什么呢?

  • 我应先提交然后再执行第二次查询吗?
  • 如果是,那么如何确保在更新之前没有其他实例读取同一行?

我想这与我正在使用的数据库没有关系。

如果我评论第二个,代码可以正常工作。如果我单独执行第二个,它也可以。

1 个答案:

答案 0 :(得分:1)

选项1 - 对于将是悲观锁定的curor执行select for update

选项2 - 执行乐观锁定并处理异常。锁需要一个列,如上次更新的时间或版本:

OPEN CURSOR

UPDATE table set col = :new_value
WHERE id = :id_from_cursor
last_updated = :last_updated_from_cursor;

CHECK if update row count == 1 COMMIT
IF not throw exception

虽然我认为选项1应该可以很好地工作,除非你选择&和更新