2

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

  1. 正在更新表的事务是分布式的,所以我无法控制它,
  2. 白天必须同时支持数千个非阻塞事务,让我们称它们为“通用”操作,
  3. 每个“通用”操作都更新了特定“分支”(“LDN”、“NY”、“LA”...)上的行,
  4. 每天一次,每个分支都有一个“主”操作,这些操作在不同的分支上大量发生,
    1. 在“主”操作期间,该分支上不会发生“一般”操作。
    2. 当“master”操作开始时,它必须等待当前“general”操作完成提供的分支,这些操作在“master”操作到达之前就在系统中。
    3. 在特定分支的“主”处理期间,可以更新所有其他分支。

为了存档,我创建了 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. 当“主”操作到来时,我开始单独的事务,其中:
    1. 在 EXCLUSIVE 模式下锁定 BRANCH_LOCK 表,当在另一个事务中在该表上存在 SHARE 模式 LOCK 时,该事务无法获取(这样,我保证在所有当前的“一般”操作完成后,“主”操作将开始,尽管它等待完成所有分支上的事务,而不仅仅是指定一个),
    2. 将分支的标志设置为“Y”(这样,我保证在“主”操作处理时不会有“一般”事务),
  2. 在传入事务中,我将表中的标志更改为“N”,因此在它提交后,BRANCH_LOG 表将在 FLAG 列中具有适当的值,并且系统将能够再次处理“一般”操作。

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

一些我没有提到的更新:

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

3 回答 3

2

与其建立自己的锁表,我想我会尝试使用 Oracle 的锁包DBMS_LOCK。

它比使用 DML 做锁更有效,并且是 Oracle 在内部使用来执行排队锁定的。

于 2011-02-02T16:29:14.203 回答
2

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

于 2011-02-02T12:30:08.957 回答
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 解决方案。

于 2011-02-02T23:40:54.867 回答