首先让我举一个例子。这是一张日志表。
用户A订阅服务A = OK
用户A取消订阅服务A = OK
用户A再次订阅服务A = OK
用户A再次订阅服务A = 不行,因为您无法同时订阅相同的服务。
有时客户端发疯并同时发送5个订阅请求(后面有4个tomcat服务器),如果我在这种情况下什么都不做,那么就会插入5个相同的记录。
如您所见,我不能在这里使用唯一约束。 我想也许我可以在Oracle中使用一些单线程块,但不确定.. 我试过“合并”,但我猜它是用于特定记录而不是最后一条记录。
开始单线程
是否有可能以及如何实现?
答案 0 :(得分:1)
也许您需要检查user id
和service type
。如果同一user
尝试在执行上一个订阅的service
之前订阅相同的service
,则提醒user
。
或者您可能希望将user
限制为仅在某段时间内订阅,例如: user
每天只能订阅相同的服务 < / p>
如果记录已存在,您可以更新记录,例如:
进行查询以检查具有特定用户和服务的记录是否存在:
SELECT * FROM table WHERE userid = userid AND serviceid=serviceid
如果查询返回任何结果,则表示存在。然后做更新:
UPDATE table SET column1='value', column2='value2' ... WHERE userid = userid AND serviceid = serviceid
否则,如果没有返回结果,则表示用户尚未订阅该服务。然后插入记录:
INSERT INTO table(column1, column2, ...) values ('value1', 'value2', ...)
答案 1 :(得分:1)
我认为你可以用约束来解决这个问题。当用户订阅它时,在取消订阅时插入一行将其删除。对于相同的用户和相同的服务,行必须是唯一的。
如果您不想删除行,请在此表中添加ACTIVE列,并对USER + SERVICE + ACTIVE进行约束。
答案 2 :(得分:0)
我不完全理解你的问题,但似乎你需要在某处实现互斥。你尝试过SELECT ... FOR UPDATE吗?
答案 3 :(得分:0)
我试过“MERGE”和子查询来解决这个问题。 顺便说一句,这个问题只发生在订阅时。首先,我从用户和服务的最后一条记录中获取状态(订阅或取消订阅)。如果表中的最后一个状态是“subscribe”,则表示此订阅的请求可能是重复的请求。
MERGE INTO subscr_log M
USING
(SELECT status
FROM subscr_log
WHERE rid=
(SELECT MAX(rid)
FROM monthly_subscr_log
WHERE SCRID ='123456'
AND service_item='CHANNEL1'
)
) C
ON (C.status ='SUB' ) -- try to see the last record is subscribe or not
WHEN MATCHED THEN
UPDATE SET M.REASON='N/A' WHERE M.STATUS='XXXXXXX' --do impossible sql
WHEN NOT MATCHED THEN
INSERT VALUES (9999,8888,'x','x','x','x','x','x','x','x','x',sysdate,'x','x','x','x');