防止更新和插入之间的异步读取

时间:2014-03-03 19:25:27

标签: c# oracle plsql

我有一个同事正在处理遇到问题的应用程序。他使用SqlCommand.ExecuteNonQuery启动存储过程。此存储过程在同一个表中更新一行并插入另一行。与此同时,他的申请继续从表中读取。在更新和插入之间发生读取时会发生竞争条件。

有问题的数据是访问级别的记录。当访问级别更改时,它会终止(更新)旧的访问级别,然后实例化(插入)新的访问级别。不经常读取将在更新和插入之间进入,并且只找到终止的访问级别 - 这有点问题。

对我的同事问题最好的解决方案是什么?

<小时/> 我抓住了他试图解决的存储过程:

BEGIN
SELECT OBJECT_ACCESS_ID, PERSON_AUTH_LEVEL
INTO lAccessID, lExistingAccessLevel
FROM SHPAZ.SH_PAZ_OBJECT_ACCESS
WHERE
    USER_ID = pUserID
    AND (GRGR_ID = pGroupID OR (GRGR_ID IS NULL AND pGroupID IS NULL))
    AND SYSDATE BETWEEN OBJECT_ACCESS_EFF_DATE AND OBJECT_ACCESS_END_DATE
FOR UPDATE;

-- If the new access level is the same as the existing, then do nothing.
IF lExistingAccessLevel = pLevel THEN
    RETURN;
END IF;

-- Terminate the existing record.
UPDATE SHPAZ.SH_PAZ_OBJECT_ACCESS
SET OBJECT_ACCESS_END_DATE = SYSDATE
WHERE OBJECT_ACCESS_ID = lAccessID;

-- Create the new record.
SELECT CASE WHEN pGroupID IS NULL THEN 'Broker' ELSE 'Employer' END
INTO lSource
FROM DUAL;

INSERT INTO SHPAZ.SH_PAZ_OBJECT_ACCESS (USER_ID, GRGR_ID, SOURCE, PERSON_AUTH_LEVEL, OBJECT_ACCESS_EFF_DATE, OBJECT_ACCESS_END_DATE) 
VALUES (pUserID, pGroupID, lSource, pLevel, SYSDATE, TO_DATE('12/31/2199', 'MM/DD/YYYY'));

COMMIT;
EXCEPTION
-- If there is no record, then just create a new one.
WHEN NO_DATA_FOUND THEN
    SELECT CASE WHEN pGroupID IS NULL THEN 'Broker' ELSE 'Employer' END
    INTO lSource
    FROM DUAL;

    INSERT INTO SHPAZ.SH_PAZ_OBJECT_ACCESS (USER_ID, GRGR_ID, SOURCE, PERSON_AUTH_LEVEL, OBJECT_ACCESS_EFF_DATE, OBJECT_ACCESS_END_DATE) 
    VALUES (pUserID, pGroupID, lSource, pLevel, SYSDATE, TO_DATE('12/31/2199', 'MM/DD/YYYY'));
END SHSP_SET_USER_ACCESS; 

1 个答案:

答案 0 :(得分:0)

解决方案是从您的程序中删除commit并获得它 在程序返回后完成。我们假设您创建名为my_procedure的程序:

SQL> exec my_procedure(my_in_arg, my_out_arg);
SQL> commit;

当原子功能操作包装在交易中时,根本不应该有种族