锁定Oracle行使第二个线程无法读取数据

时间:2015-05-22 13:28:11

标签: sql multithreading oracle

如何阻止一个线程的事务读取一行直到另一个事务处理完毕?

我在Oracle 11 DB上有一个触发器表。触发器表上的一行有一个状态标志,用于指示是否需要进行处理 - 让我们说它可以触发电子邮件。有一个abatch进程定期轮询触发器表。这个过程是:

  1. 获取状态为NOT_SENT的X个触发器
  2. 将X触发器的状态更新为SENDING
  3. 发送X电子邮件
  4. 将X触发器的状态更新为SENT
  5. 但我正在群集环境中运行我的应用程序。因此可能有多个版本的批处理过程并行地拉下触发器。我想确保竞争批处理过程不会拉下相同的触发器并执行相同的处理,即发送相同的电子邮件。

    我正在查看Oracle SELECT FOR UPDATE子句。但是,如果这样做我想要的话,我不是100%清楚。我需要线程A锁定触发器行和线程B以阻止读取或写入触发器行。如果SELECT FOR UPDATE阻止线程B读写,或者阻止线程B仅写入,则不是100%清楚。我需要前者。

    欢迎思考。

2 个答案:

答案 0 :(得分:2)

SELECT FOR UPDATE锁定并读取行。如果线程A已锁定该行并且线程B试图锁定它,则线程B将阻塞,直到线程A释放其锁定。因此,如果A和B都在执行SELECT FOR UPDATE,则线程B将等待直到A完成。

在Oracle中,读者永远不会被编写器阻止,因此其他线程可以自由地读取A正在处理的行。他们只是无法锁定行。

当然,如果您的锁定机制将您的应用程序转换为功能上单线程的东西,它就会失去拥有多个线程的目的。你可能想看一下SELECT FOR UPDATE SKIP LOCKED。这是how SKIP LOCKED works的一个很好的例证。

答案 1 :(得分:1)

在PL / SQL块中(触发器也是PL / SQL块),您可以使用dbms_lock包。