【问题标题】:Oracle DB lock table useOracle DB锁表使用
【发布时间】:2011-06-19 22:41:12
【问题描述】:

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

  1. 正在更新的事务 桌子是分发的,所以我没有 控制它,
  2. 白天 数千个非阻塞事务 必须同时支持, 让我们称它们为“一般”操作,
  3. 每个“常规”操作都会更新特定“分支”(“LDN”、“NY”、“LA”...)上的行,
  4. 一天有一个“主人” 每个分支的操作​​,这些操作在不同的分支上大量发生,
    1. “主”操作期间无 该分支上的“一般”操作可能会发生。
    2. 当“主”操作启动时 必须等待当前的“将军” 对提供的分支完成操作, 在“主”操作到达之前就在系统中。
    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” (这样,我保证在“master”时不会有“general”交易 运算处理),
  2. 在传入事务中,我将表中的标志更改为“N”,因此在 它提交 BRANCH_LOG 表将有 FLAG 列中的适当值,系统将 能够处理“一般” 再次操作。

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

一些我没有提到的更新:

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

【问题讨论】:

  • 我不清楚你的观点 (1)。它被分发与你是否可以控制它有什么关系?另外,这是指一般操作还是主操作?
  • 您暗示但没有直接声明,同一分支上的多个常规操作可以同时工作。对吗?
  • 关于 cmets。关于第 1 点,所有操作 general 和 master 都是分布式的,所以我不知道事务何时开始,何时提交或回滚,在这个时间点我无法控制。关于一般操作,在支持的同一分支上必须每秒有 3'000 操作,所以是的,一个分支同时有多个操作,同时发生。

标签: oracle transactions locking distributed xa


【解决方案1】:

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

【讨论】:

  • 这是一个业务需求,在'master'操作中不要进行一般操作,并且在'master'操作开始时不能有当前的'general'操作,否则会出现数据不一致的情况。此外,“主”操作需要的时间是一般操作的 1000 倍。
  • 安东,所有数据都由oracle数据库管理吗?或者数据是否也在文件上管理?如果仅由 oracle 数据库管理,则不会因为读取一致视图而出现问题。如果应该与数据库一致的数据也在数据库之外,我会认真重新考虑那部分。
  • 所有信息都存储在 Oracle DB 中。我不认为一致性在这里起作用,因为主操作必须处理白天一般操作所做的更改,重要的是,不会丢失任何“一般”操作。因此,如果当前的“一般”操作进行了未提交的更改,那么主操作将看不到它们,并且在主进程中丢失,这是不可接受的。所以一致性在这里不起作用。
  • 我可以看到缺少更新并不好玩。因为这是我的下一个问题:在主进程完成并释放锁之后提交的事务会发生什么?我可以想象该应用程序有某种方式来识别新交易?如果这是基于时间的,您将搜索在最后一次主运行的开始日期之后创建的新 tx。如果是这样的话,如果你问我,你可以使用正常的读取一致视图。
  • 我想,如果'general'和'master'事务会修改同一行呢?一个会在 NUMBER 行中设置 5,另一个会设置 10。结果会是什么,哪个更新会丢失?从业务角度猜测是不可接受的。并且系统必须保证不会丢失任何东西。所以从我的角度来看,一致性读取并不是一个真正的选择。商家还会收到客户抱怨更新延迟,这也是不可接受的。
【解决方案2】:

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

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

【讨论】:

  • 好的,我其实不是DBA,我是开发人员,所以不知道有这个能力,我去看看,谢谢。
  • 您的 DBA 可能需要授予您执行此软件包的权限。
【解决方案3】:

什么是表卷。

我会考虑让主操作像

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 解决方案。

【讨论】:

  • 是的,交易量很大,它是金融产品,几乎每天都有数据重复,其中有数百万条记录。虽然我们在 DB 中有这种锁,其中包含更改记录的部分 PK,但没有日期。但是有一个问题,如果新事务在这个分支中创建了新记录,那么提供的查询不会看到这条记录。因此,此更新将丢失。另外,从我的角度来看,最好在一个表的一条记录中设置一个标志,而不是在另一个表中锁定 1'000'000 条记录。
猜你喜欢
  • 1970-01-01
  • 2015-04-24
  • 1970-01-01
  • 2020-03-22
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多