如何避免影响单个实体的并发事务

时间:2015-01-08 21:01:41

标签: java multithreading oracle weblogic middleware

HELP!
案例是指两个或多个交易试图影响某个外部系统中的同一客户货币账户。我需要执行第二个事务,直到第一个事务完成。
考虑:
- 有两个或更多交易试图影响相同的余额
- 同时有多个客户
- 使用1000 TPS,每次交易平均100毫秒
的想法:
- 因为我们正在使用多线程来支持1000TPS,我试图根据客户端ID创建队列。使用某种由客户端限制一个线程的工作管理器。因此,如果我有2个同时具有相同clientID的请求,则动态地可以排队第二个。

工具
我试图使用Oracle工具,例如:
- 融合中间件:使用基于消息上下文的Workmanager [不确定是否可能因为上下文只能基于会话数据]我喜欢WorkManager因为没有性能问题
- Oracle OCEP:使用CQL创建动态队列[尽可能不确定和性能]
- Oracle Advance Queuing:可能与事务组一起使用。

感谢任何想法

1 个答案:

答案 0 :(得分:0)

我希望我能解决你的问题。

在你问的问题中,在第一次完成之前,可以在一行上执行第二次交易。这是不可能的!遵循A C ID范例的数据库必须 C onsistent!所以你不能“超越”第一笔交易!如果你想这样做,你应该使用NoSQL数据库(如MongoDB,......),其中一致性不是很强。

但是也许你想知道,如果有一个Oracle视图可以搞清楚,是否锁定了一行?让我们假设,有一个这样的观点。您将检查此视图,如果没有锁定,则开始更新/删除。但是你无法确定这是否可行,因为即使你检查它后1ms,另一个进程也可以锁定它。

你唯一能做的就是在UPDATE / DELETE语句之前加上“select ... for update NOWAIT ”。 如果该行被锁定,您将收到异常(ORA-00054:资源繁忙)。这是推荐/“开箱即用”的方式让数据库为您管理行级锁定!

使用emp表查看以下示例。考虑一下:要检查一下,请在两个不同的会话中同时启动此代码。

declare
  l_sal number;
  resource_busy exception;                    -- declare your own exception
  pragma exception_init (resource_busy, -54); -- connect your exception with ORA-00054

begin
   select sal
     into l_sal 
     from emp 
     where empno = 7934
   for update NOWAIT;

   update emp
   set sal = sal + 100
   where empno = 7934;

   exception
     when resource_busy then
       null;  -- in your case, simply do nothing, if the row is locked

end;