Sql 乐观锁的原子性

Sql 乐观锁的原子性,sql,database,oracle11g,Sql,Database,Oracle11g,我使用Oracle 11g(它可能会对解决方案产生影响)。我已经对如下表进行了版本控制。我想进行原子操作,包括从这个表中选择、插入到另一个表(取决于前一个表的状态)和更新前一个表的状态 我想要简单的解决方案(简单的问题简单的解决方案?),我想要避免死锁。我选择乐观锁定策略 所以,我有这样的桌子 CREATE TABLE table ( id int, version int, state varchar(20) ); 在伪代码中,我有如下内容: Line 1: SET

我使用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行之间执行相同的代码块。然后(考虑到隔离级别=read committed),我有两个插入到
other_table
,我不想这样做

如何使这个代码块真正原子化


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

无需干扰隔离级别,您可以先执行
更新
,如果更新成功,则执行
插入操作。更新将锁定受影响的行(),因此另一个会话将被阻止,直到第一个会话关闭其事务

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;
/

如果您的dbms使用乐观并发控制,您将永远不会遇到任何死锁。事务是一种原子操作。您是否考虑了特定的RDBMS?是的,它是Oracle 11g.Hm。。您确定更新会在事务结束前锁定受影响的行吗?你能分享一些文档的链接吗?当然,看看。您也可以自己尝试,在两个SQL*Plus会话中执行代码,而不关闭事务。