Oracle SELECT FOR UPDATE忽略已锁定的记录

时间:2013-09-25 01:17:34

标签: oracle oracle11g locking dao

我们有一个高事务性,高并发java系统访问存储在Oracle 11.g实例上的数据。我们的系统部署在多个Websphere 8.5应用服务器上。 对数据的并发访问由在不同线程中运行的不同事务进程执行。

请考虑下表,其记录应遵循以下规则处理:

  1. ID只是一个序列号,表示首先创建了哪条记录。
  2. 没有要求ID是连续的号码,但是确保在ID> 1的记录之前插入了ID = 1的记录。 1
  3. 必须按ID顺序处理具有相同BUSINESS_ID的记录(例如,对于BUSINESS_ID = 1,处理订单必须为ID = 1,2,4)
  4. 如果某个线程正在处理具有BUSINESS_ID的记录,则其他线程不应处理具有相同BUSINESS_ID的记录。
  5. 另一个线程可以开始处理具有当前未由任何其他线程处理的BUSINESS_ID的最小ID的记录。
  6. 处理记录完成后,记录将从表中删除。
  7. ID BUSINESS_ID

    ==============
    1       1
    2       1
    3       2
    4       1
    5       3
    6       3
    7       2
    

    要创建测试数据,您可以运行以下命令:

    create table test (id number, business_id number);
    insert into test values (1, 1);
    insert into test values (2, 1);
    insert into test values (3, 2);
    insert into test values (4, 1);
    insert into test values (5, 3);
    insert into test values (6, 3);
    insert into test values (7, 2);
    commit;
    

    要模拟三个线程,您可以为每个线程打开一个单独的数据库会话。在这种情况下,处理流程可能如下所示:

    1. 线程A:查找工作并获取记录ID = 1(当前未处理的记录BUSINESS_ID的最小ID)这将锁定记录ID = 1
    2. 线程B:查找工作并获取记录ID = 3(当前正由线程A处理的BUSINESS_ID = 1阻止线程B获取记录ID = 2)
    3. 线程C:查找工作并获取记录ID = 5(线程A和B当前正在处理BUSINESS_ID = 1和2)
    4. 线程A:完成工作并删除记录ID = 1并提交工作。 线程A:寻找工作并获得记录ID = 2
    5. 依旧......
    6. 我的想法是使用SELECT FOR UPDATE来标记要处理的记录,以及何时完成工作以删除并提交所选记录。

      使用存储过程实现此逻辑将起作用,但我们的方法是将业务逻辑保留在Java代码中的中间层级而不是数据库级别。

      您是否可以通过运行SQL而不是在存储过程中实现它来看到实现此目的的方法?

      因此,简而言之,我所拥有的是具有最小ID的记录的SELECT FOR UPDATE,其中BUSINESS_ID不属于该表中任何其他锁定记录。

      提前谢谢

0 个答案:

没有答案