【问题标题】:oracle select & update or select & insert in multithreaded envoracle select & update 或 select & insert 在多线程环境中
【发布时间】:2013-04-03 19:53:53
【问题描述】:

我有一个问题,我觉得解决方案很简单,但我想不通。

A 有一个多线程环境和一个 pl sql 存储过程。 在这个过程中,我有类似的东西:

select * into mycount from toto;
If mycount >0 then update...;
else insert ...;

问题是我有很多线程调用这个过程。 有没有一种简单的方法可以一次只让一个线程执行上面的代码? 我知道我可以使用select for update,但因为我可以有一个 UPDATE 或 INSERT 我想这对我不起作用。

非常感谢。

【问题讨论】:

  • 尝试在过程调用的末尾添加一个提交,这样线程就不会在你的表上保持独占的 DML 操作。任何 DDL 都可能打破锁。
  • 第一个select 不是必需的。只需运行update 并检查更新的行数。它为零,执行插入(这样“选择”只会执行一次)。或使用MERGE 语句。

标签: sql multithreading oracle plsql


【解决方案1】:

有一个单独的表 MODIFY_CHECKER,只有一列 FLAG。使用此表和列作为一种方法,仅允许一个线程在您的实际表上更新/插入(我想是 TOTO)

您可以在现有的 PL/SQL 过程中添加类似下面的内容 -

IF (select count(1) from modify_checker where flag = 1) > 0 THEN
  -- Another thread is already working, so just raise exception
  RAISE <<exception>>
ELSE
  -- No other thread working on this, so go ahead
  UPDATE modify_checker SET flag = 1;
  COMMIT;
  <<actual code to update or insert actual table>>
  UPDATE modify_checker SET flag = 0;
  COMMIT;
END IF;

【讨论】:

    【解决方案2】:

    您想要的最简单的解决方案是在应用程序级别引入某种中间队列 - 各种线程会将请求发送到队列,队列处理器将从队列中读取请求并进行必要的处理调用数据库。

    在我看来,这将是最简单的解决方案,因为您无需进行太多更改即可使其正常工作。唯一潜在的问题是,如果需要响应,此解决方案可能会很复杂 - 如果是这样,这仍然是一种选择,但由于必须处理异步响应,应用程序代码会有点复杂。

    【讨论】:

    • 好主意,但我无法实现它,因为我的存储过程在不同的地方调用,我无法修改每一段代码。
    • 您必须修改代码才能使任何解决方案正常工作。您将无法从 SQL 服务器执行任何操作。
    • 另一种选择是让当前的 proc 充当“队列”,然后调用一个新的 proc,可能使用 Oracle AQueues 之类的东西。不过,根据我对 AQ 的经验,这可能很繁琐。如果您不想更改客户端代码,那么我认为这些方面的内容可能是您唯一的选择
    【解决方案3】:

    您可以在访问该过程时立即加锁,并在退出时释放它。这样一次只有一个人可以访问它。

    ALTER TABLE tl_test ENABLE TABLE LOCK;

    ALTER TABLE tl_test DISABLE TABLE LOCK;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      • 2021-10-27
      • 2011-01-29
      • 2013-07-12
      • 1970-01-01
      相关资源
      最近更新 更多