如何在 SQL 过程中管理并发访问



我在我的预言机数据库中创建了一个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;

当两个用户同时调用此过程时,我能做些什么,他们得到一组不同的行。

谢谢。

"每个条目只能处理一次的条件。

这听起来像是排队。通常的管理方法是使用 SELECT 实现队列......对于更新跳过锁定光标。这里有一个非常重要的警告:您在问题中提到的处理包括影响初始标准的内容,例如通过更新状态值或删除识别记录(或其他任何内容 - 不幸的是,对其细节含糊不清的问题只能吸引同样模糊的答案(。

所以它可能会锁定这样的东西(显然是指示性代码(:

  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 子句的列将防止多次处理同一记录。

当两个用户在 同时,它们会得到一组不同的行。

您可以修改查询并使用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

最新更新