Oracle DB锁表使用

时间:2011-02-02 12:08:19

标签: oracle transactions locking distributed xa

最近我有一个任务,根据该任务,我需要具有特定的锁定功能。具体原因是:

  
      
  1. 正在更新的交易   桌子是分发的,所以我没有   控制它,
  2.   
  3. 白天   数千次非阻塞交易   必须同时支持,   我们称之为“一般”操作,
  4.   
  5. 每个'一般'操作更新特定'分支'上的行(“LDN”,“NY”,“LA”......),
  6.   
  7. 每天一次有一个'主人'   每个分支机构的操作,在不同的分支上进行,   
        
    1. 在'主'操作期间没有   该分支上的“一般”操作可能会发生。
    2.   
    3. 当'master'操作启动时   必须等待当前'一般'   对提供的分支机构完成的操作,   在“主人”行动到来之前,这些都在系统中。
    4.   
    5. Durring'master'在特定分支上的处理,所有其他分支都可以   更新。
    6.   
  8.   

为了存档,我创建了Oracle DB特定表

create table BRANCH_LOCK(
    BRANCH VARCHAR2(10),
    FLAG   VARCHAR2(1),
    CONSTRAINT "PK_BRANCH_LOCK" PRIMARY KEY ("BRANCH")
)

支持不同操作的以下功能:

对于“一般”操作:

1. In the same XA transaction each operation locks BRANCH_LOCK table 
   in SHARE mode,
2. After locking it checks FLAG, on updated branch,
  1. If flag is 'Y', that means that currently 'master' 
      operation is in progess, so  Exception is thrown, 
     and no further processing is done;
  2. If flag is 'N' than everything is OK, and general processing is done;

对于'主'操作:

  
      
  1. 当'master'操作到来时,我开始单独的交易:   
        
    1. 在EXCLUSIVE模式下锁定BRANCH_LOCK表,当该表在另一个事务中存在SHARE模式LOCK时,该事务无法获取(这样,我保证'master'操作将在所有当前'general'操作完成后启动,虽然它等待所有分支机构的交易   完成,不仅指定一个),
    2.   
    3. 将分支的标志设置为“Y”   (这样,我保证在'主'时不会有'一般'交易   运作处理),
    4.   
  2.   
  3. 在传入的事务中,我将表中的标志更改为“N”,因此在之后   它提交BRANCH_LOG表会有   FLAG列中的适当值,系统会   能够处理'一般'   再次开展业务。
  4.   

这还没有投入生产,所以我想知道是否有更好的解决方案, 并且除了描述之外还有其他缺点吗?

一些更新,我没有提及:

  1. 'Master'操作适用于'一般'操作的结果,所以至关重要的是,在'master'处理期间没有'一般'操作丢失,所以这就是为什么当前'一般'操作必须在master之前完成操作开始处理。
  2. 同一分支上的多个“通用”操作每秒发生一次,每秒3,000次操作,
  3. 只能对分支执行一次“主”操作,可以同时处理不同分支上的多个“主”操作。

3 个答案:

答案 0 :(得分:2)

安东, 为什么你需要手动锁定表[s]?通常没有必要这样做。当您描述的主操作启动时,它将获得在该主事务开始时提交的数据的读取一致视图。一般事务可以继续工作,并且您描述的主事务将不会看到更改,直到它启动新事务。

答案 1 :(得分:2)

我认为我不会构建自己的锁定表,而是尝试使用Oracle的锁定包DBMS_LOCK.

它比使用DML做锁更有效,也是Oracle内部用来执行入队锁定的。

答案 2 :(得分:0)

表卷是什么。

我会考虑让主操作像

一样启动
CREATE OR REPLACE PROCEDURE do_master (in_branch IN VARCHAR2) IS
BEGIN
  SELECT ...
  BULK COLLECT INTO
  FROM ...
  WHERE branch = in_branch
  FOR UPDATE OF branch;
  ...
END do_master;

那将使用标准的Oracle锁定来确保do_master等待直到锁定这些分支的未完成的常规事务完成,然后do_master停止任何其他常规更新,直到它提交为止。然后这些一般更新恢复。

但是如果卷很大,那么SELECT ... FOR UPDATE可能非常大。那是我考虑使用DBMS_LOCK解决方案的时候。