【问题标题】:Atomicity of optimistic locking乐观锁的原子性
【发布时间】:2015-10-21 08:46:22
【问题描述】:

我使用 Oracle 11g(它可能对解决方案有影响)。我有如下版本的表格。我想做原子操作,包括从这个表中选择,插入另一个表(取决于前一个表的状态)和更新前一个表的状态。

我想要简单的解决方案(简单的问题简单的解决方案?),原子的,我想避免死锁。我选择乐观锁定策略。

所以,我有这样的桌子

CREATE TABLE table (
    id int,
    version int,
    state varchar(20)
);

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

Line 1: SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Line 2: START TRANSACTION;
Line 3: SELECT state as S, version as V from table where id = X;
Line 4: if (S == 'TODO') then 
Line 5:     INSERT INTO other_table ...
Line 6:     UPDATE table SET state = 'DONE', version = version + 1 WHERE id = X and version = V
Line 7: COMMIT;

据我了解 SQL 事务,另一个线程可以在第 6 行和第 7 行之间执行相同的代码块。然后(考虑到隔离级别 = 已提交读取)我有两个插入到 other_table 中,我不想这样做。

我怎样才能使这个代码块真正原子化?

我想避免锁定行和序列化隔离级别(死锁)。

【问题讨论】:

  • 如果您的 dbms 使用乐观并发控制,您将永远不会遇到任何死锁。事务是原子操作。
  • 您有特定的 RDBMS 吗?
  • 是的,它是 Oracle 11g。

标签: sql database oracle11g


【解决方案1】:

不用纠结隔离级别,可以先UPDATE,如果更新成功,再做INSERT。更新将锁定受影响的行 (oracle documentation here),因此另一个会话将被阻止,直到第一个会话关闭其事务。

PL/SQL 示例:

BEGIN
  UPDATE t
     SET state = 'DONE', version = version + 1
   WHERE id = x
     AND state = 'TODO';

  IF( SQL%FOUND ) THEN
    dbms_output.put_line( 'INSERT HERE' );
  END IF;
END;
/

【讨论】:

  • Hm.. 你确定更新会锁定受影响的行直到事务结束吗?你能分享一些文档链接吗?
  • 当然,看看Automatic Locks in DML Operations。您也可以通过在两个 SQL*Plus 会话中执行代码而不关闭事务来自己尝试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 2011-02-23
  • 2013-06-30
  • 1970-01-01
相关资源
最近更新 更多