我有一个同事正在处理遇到问题的应用程序。他使用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;
答案 0 :(得分:0)
解决方案是从您的程序中删除commit
并获得它
在程序返回后完成。我们假设您创建名为my_procedure
的程序:
SQL> exec my_procedure(my_in_arg, my_out_arg);
SQL> commit;
当原子功能操作包装在交易中时,根本不应该有种族。