如何避免并发事务插入的重复ID?

时间:2012-07-23 06:21:33

标签: sql oracle plsql

我在多个会话中执行了PL / SQL:

DECLARE
   x     NUMBER;
   y     NUMBER;
BEGIN
   x := 500;
   y := 0;
   WHILE (x > y)
   LOOP
       SET TRANSACTION 

       Select max(SERIAL_NO) INTO y from MY_TABLE;

       y := y + 1;

       insert into MY_TABLE S (S.SERIAL_NO, S.Request_id)
       values ((
                (select max(SERIAL_NO) from MY_TABLE) + 1
               )
              ,'B');

       Commit;

   END LOOP;
END;
/

我仍然在表格中有重复的条目,这怎么可能发生?

2 个答案:

答案 0 :(得分:4)

不确定。 Oracle具有读取提交的事务隔离级别。

如果两个会话运行如下:

Time  Session A                                 Session B
1     (Select max(SERIAL_NO) from MY_TABLE)+1
2                                               (Select max(SERIAL_NO) from MY_TABLE)+1
3     commit;

您将在表格中获得SERIAL_NO的重复项,因为会话A + B看到SERIAL_NO的值相同。

您需要使用序列来确保唯一性(或实现您自己的信号量 - 但我不建议这样做。)

您的SET TRANSACTION语句缺少某些参数,但无论如何这都无济于事(如果您想到SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

另请参阅关于可序列化隔离事务级别和数据并发性和一致性的http://docs.oracle.com/cd/B19306_01/server.102/b14220/consist.htm#sthref1981

答案 1 :(得分:1)

如果您不想在表格中使用重复项,请使用UNIQUE CONSTRAINTS。