我已经在oracle数据库中创建了一个sql过程,稍后将在我的c#代码中调用
此过程的主要目标是循环进入条目并进行处理,以使每个条目只能被处理一次。
过程的主体看起来像这样。
FOR item IN
( SELECT * FROM
(SELECT tab1.item1,tab1.item2,tab1.item3...
FROM tab1
INNER JOIN tab2 ON ...condition...
INNER JOIN TAB3 ON ...condition...
WHERE ....main_condition=true;
ORDER BY tab1.item1
)
WHERE ROWNUM < in_param
)
LOOP
.
.
.
dbms_lock.sleep(4);
.
.
.
"set main_condition=false;"
commit;
END LOOP;
当两个用户同时调用此过程时,他们将获得不同的行集,该怎么办?
谢谢。
答案 0 :(得分:2)
“每个条目只能被处理一次的条件”。
这听起来像一个队列。通常的管理方式是使用SELECT…FOR UPDATE SKIP LOCKED游标实现队列。这里有一个非常重要的警告:您在问题中提到的治疗包含会影响初始标准的内容,例如,通过更新状态值或删除身份记录(或任何其他问题-不幸的是,问题含糊其词的细节只能吸引同样含糊的答案。
因此它可能会锁定这样的东西(显然是指示性代码):
cursor c_whatever is
SELECT tab1.item1,tab1.item2,tab1.item3...
FROM tab1
INNER JOIN tab2 ON ...condition...
INNER JOIN TAB3 ON ...condition...
WHERE tab1.main_condition = true
FOR UPDATE OF tab1.main_condition SKIP LOCKED ;
begin
open c_whatever;
….
update tab1
set tab1.main_condition = false
where tab1.item1 = ….
commit;
悲观锁定将防止两个会话抓住同一行。更新提供给WHERE子句的列将防止同一记录被多次处理。
答案 1 :(得分:1)
当两个用户在 同时,他们获得了不同的行集。
您可以修改查询并使用ORDER BY DBMS_RANDOM.VALUE
来获取随机行。因此,您可以将查询修改为
SELECT * FROM
(SELECT tab1.item1,tab1.item2,tab1.item3...
FROM tab1
INNER JOIN tab2 ON ...condition...
INNER JOIN TAB3 ON ...condition...
WHERE ....main_condition=true;
ORDER BY DBMS_RANDOM.VALUE