我在网上搜索了一些简单的例子,但无济于事。我需要在Java中使用JDBC作为原子单元运行select
和insert
操作。
实际上我需要做以下事情:
这通常是一个简单的操作,但由于我的应用程序是多线程的,我不知道如何解决这个问题。因为同时运行的并发线程可以尝试使用相同的代码值插入。
我可以考虑使用几种解决方法或黑客来完成这项工作,但一般来说如何锁定表以使此操作成为原子?我见过的大多数都涉及行锁,但由于我没有更新,我不知道这是如何适用的。
答案 0 :(得分:1)
这完全是在SQL中完成的一个难题。任何解决方案都会遇到竞争条件问题。如果我要在SQL中完全使用SQL,我会使用已删除的代码表。当用户随后被删除时,您将使用某些服务将其代码添加到已删除的表中。如果删除的代码表为空,则线程将使用序列号来获取其新代码。从已删除的代码中获取代码需要位于synchronized
块中,因为get和then set nature具有多个SQL操作。我不认为SQL事务会对那里有所帮助。它们可以保持数据一致,但如果两个线程使用相同的代码,那么两个提交中的一个将引发异常。
我认为更好,更快的机制是让一个单独的线程管理这些删除的代码。它可以将其写入数据库,但也保留BlockingQueue
个已删除的代码供其他线程使用。如果必须没有漏洞并且您担心崩溃,则需要通过在启动时查询用户表来验证可用漏洞列表。它不需要同步或执行任何SQL事务,因为它只会从已删除的代码表中删除。
希望这有帮助。
答案 1 :(得分:1)
我倾向于将逻辑放在存储过程中。使用“select for update”锁定,然后提交解锁。
您可以在insert语句中添加一个过滤器,并在客户端重试逻辑,我想:
插入内容会沿着这些行显示,其中3是您的新ID,'Joe'是您的新用户,并建议编码您认为可用的那个:
INSERT INTO users
SELECT 3, :proposedCode, 'Joe'
FROM dual
WHERE :proposedCode NOT IN (SELECT code FROM users)
答案 2 :(得分:1)
怎么样:
insert into usertable (
id,
code,
name
) values (
user_id_sequence.nextval,
(
select min(newcode)
from usertable, (
select level newcode
from dual
connect by level <= (select max(code)+1 from usertable))
where not exists (select 1 from usertable where code = newcode)
),
'mynewusername'
)
编辑:
更改为max(code)+ 1,因此如果没有可用的间隙,则可以使用新代码。