并发控制问题

hu_anqing 2009-01-15
我orcale一个函数中要实现并发控制又要能控制查询的记录没有的情况,这样应该怎么写才能实现
如:
SELECT NVL("Seq_MaxID",0) INTO maxSequence FROM "_T_Sequences" WHERE "Seq_TableName" = tableName for update;  这样实现了并发控制,但如果查询记录没有时就要报no data found错误

SELECT NVL(max("Seq_MaxID"),0) INTO maxSequence FROM "_T_Sequences" WHERE "Seq_TableName" = tableName ;这样写控制了查询记录为空的情况,但是并发控制就没有了,而用了max函数以后就不能用for update


应该怎么写这句SQL才好
yuyoo4j 2009-01-15
首先使用for update 实现并发控制会导致数据库忙等待的情况.
这样你想通过for update来实现并发控制可能(可能性很大)就是你的系统的瓶颈了.
比较好的做法是:
在表"_T_Sequences"中增加一个字段来实现并发控制, 比如增加一个字段
lockFlag char(1). 当lockFlag 为 0标示未被占用, 1标示已经被占用.
下面是并发控制:
1. update "_T_Sequences" t
       set t.lockFlag = '1'
     where t."Seq_TableName" = tableName
       and t.lockFlag = '0'
   判读"影响行数"是否为1.
   如果为1说明占到 update的记录(record)了, 就可以处理业务逻辑了
   你的情况就可以 使用 select语句了, 这时不存在其他并发争用对应的记录了.
   如果为0说明其他并发已经占用了对应的记录,可以延迟一段时间(比如sleep操作)再 来尝试占用记录.
2. 当 update 为1时,业务逻辑也处理完成了.可以使用使用一个:
     update "_T_Sequences" t
       set t.lockFlag = '0'
     where t."Seq_TableName" = tableName
       and t.lockFlag = '1'
    来释放资源(也就是record).

下面讨论怎样在select into语句中避免 no data found错误,
这个可以使用一个左连接来实现.
SELECT R.target
      INTO maxSequence
      FROM DUAL L,
           (SELECT 'X' AS DUMMY, NVL("Seq_MaxID",0) AS target
              FROM "_T_Sequences"
              WHERE "Seq_TableName" = tableName
               AND lockFlag = '1') R
     WHERE L.DUMMY = R.DUMMY(+);
hu_anqing 2009-01-15
那如果肯定要用for update 呢
hu_anqing 2009-01-16
SELECT R.target
      INTO maxSequence
      FROM DUAL L,
           (SELECT 'X' AS DUMMY, NVL("Seq_MaxID",0) AS target
              FROM "_T_Sequences"
              WHERE "Seq_TableName" = tableName
               AND lockFlag = '1') R
     WHERE L.DUMMY = R.DUMMY(+) for update;

这样写会不会把查询到的记录锁起来
Global site tag (gtag.js) - Google Analytics