最近我有一个任务,根据这个任务,我需要有一个特定的锁定功能。具体是因为:
- 正在更新表的事务是分布式的,所以我无法控制它,
- 白天必须同时支持数千个非阻塞事务,让我们称它们为“通用”操作,
- 每个“通用”操作都更新了特定“分支”(“LDN”、“NY”、“LA”...)上的行,
- 每天一次,每个分支都有一个“主”操作,这些操作在不同的分支上大量发生,
- 在“主”操作期间,该分支上不会发生“一般”操作。
- 当“master”操作开始时,它必须等待当前“general”操作完成提供的分支,这些操作在“master”操作到达之前就在系统中。
- 在特定分支的“主”处理期间,可以更新所有其他分支。
为了存档,我创建了 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;
对于“主”操作:
- 当“主”操作到来时,我开始单独的事务,其中:
- 在 EXCLUSIVE 模式下锁定 BRANCH_LOCK 表,当在另一个事务中在该表上存在 SHARE 模式 LOCK 时,该事务无法获取(这样,我保证在所有当前的“一般”操作完成后,“主”操作将开始,尽管它等待完成所有分支上的事务,而不仅仅是指定一个),
- 将分支的标志设置为“Y”(这样,我保证在“主”操作处理时不会有“一般”事务),
- 在传入事务中,我将表中的标志更改为“N”,因此在它提交后,BRANCH_LOG 表将在 FLAG 列中具有适当的值,并且系统将能够再次处理“一般”操作。
这还没有投入生产,所以我想知道有没有更好的解决方案,除了描述的还有其他缺点吗?
一些我没有提到的更新:
- '主'操作对'一般'操作的结果起作用,所以在'主'处理期间没有'一般'操作丢失是至关重要的,所以这就是为什么当前'一般'操作必须在主操作开始处理之前完成.
- 同一分支上的多个“一般”操作每秒发生一次,每秒大约 3'000 次操作,
- 分支只能发生一个“主”操作,可以同时处理不同分支上的多个“主”操作。