2012-03-06 19 views
2

我已经在网上搜索了这个简单的例子,但无济于事。我需要在JDBC中针对Oracle数据库运行selectinsert操作作为Java中的原子单元。JBDC - 在并发线程中自动执行SELECT和INSERT

有效,我需要做到以下几点:从用户

  • 经过的所有代码

    1. 选择代码,直到我找到一个未使用(因为用户可以删除有可能在现有的代码范围的中间)
    2. 插入与可用的代码

    这是一个简单的操作正常,但我的应用程序是多线程的,我不知道如何去THI新用户秒。因为同时运行的并发线程可能会尝试并使用相同的代码值插入。

    有几个解决方法或黑客,我可以想到做这项工作,但总的来说,我怎样才能锁定表,使此操作原子?我见过的大多数涉及行锁,但因为我没有更新,我不明白这是如何适用的。

  • +0

    为什么不使用“插入选择”的方式。我不知道它是否适合您的需求,因为我不知道表结构。但我认为如果你可以用插入的方式进行选择,那么你的问题就会得到解决。 – Naved 2012-03-06 07:51:09

    +0

    嗨。我认为这不会起作用。我的表结构基本上是。 ID,代码,名称和说数据是1,1,约翰; 2,2,弗兰克; 4,4,鲍勃所以我想做一个选择发现代码3不使用,然后做一个插入值(5 ,3,Bill)并发多线程可能会得到3作为下一个可用的代码,并且第二个线程在尝试插入时会失败,如果选择和插入不是原子的 – user1251589 2012-03-06 08:12:51

    回答

    1

    这完全是在SQL中完成的难题。任何解决方案都会遇到竞态条件问题。如果我要完全用SQL来完成,我会使用一个已删除的代码表。当用户被删除时,你会使用一些服务将他们的代码添加到已删除的表中。如果删除的代码表为空,则线程将使用序列号来获取其新代码。从已删除的代码中获取代码需要位于​​块中,因为使用多个SQL操作的get和set性质。我不认为SQL事务会在那里帮助。他们可能保持数据一致,但如果两个线程使用相同的代码,那么两个提交中的一个将抛出异常。

    我认为一个更好,更快的机制是让单独的线程管理这些已删除的代码。它可以将其写入数据库中,但也会保留BlockingQueue已删除的代码以供其他线程使用。如果不存在漏洞并且您担心崩溃,则需要在启动时通过查询用户表来验证可用漏洞列表。它不需要同步或执行任何SQL事务,因为只有它将从已删除的代码表中删除。

    希望这会有所帮助。

    +0

    也许应该有一个包含所有“代码”的表有一个布尔分配字段。然后获取代码将是“更新代码集分配=真,其中代码=(从代码分配=假选择min(代码))返回代码到...”。如果代码有意义,那么也许他们应该被列出。如果他们没有意义,那么就不应该担心差距...... – Glenn 2012-03-07 04:24:14

    +0

    谢谢@Glenn。我不确定你是如何从该语句中获得“代码”结果的,但类似的东西会起作用。即使有了它,线程也会循环,直到更新行。我仍然认为分配器线程是要走的路。 – Gray 2012-03-07 04:28:46

    1

    我会倾向于将逻辑放入存储过程。使用“选择更新”来锁定,然后提交解锁。

    您可以将过滤器添加到您的插入语句,并在客户端重试逻辑,我想:

    • 确定可用码(推荐码)
    • 执行带滤波器的插入判定数从executeUpdate的结果行(0表示并发线程抓住了这个代码,再试一次)

    插入看起来沿着这些线路,其中3是你的新的ID,“乔”您的新用户,以及proposedCode的东西你认为有一个:

    INSERT INTO users 
        SELECT 3, :proposedCode, 'Joe' 
        FROM dual 
        WHERE :proposedCode NOT IN (SELECT code FROM users) 
    
    +0

    我认为,如果您打算仅在Java端执行逻辑,则可以使用可更新的ResultSet。如果我错了,请纠正我。 – Naved 2012-03-07 03:31:29

    +1

    @Naved老实说,我不知道。自从我尝试了几年后,我通常会将这种逻辑放入存储过程中。这样,api就可以用于任何类型的客户端,而无需客户端担心实现细节(并且服务器端不必担心客户端如何实现)。对于CRUD类型的应用程序,我会在表格上放置一个版本字段,进行读取操作,稍后在写入修改后的记录时添加“WHERE version = ”。如果没有行被更新,msg会向用户发出并发更新失败。 – Glenn 2012-03-07 04:13:31

    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' 
    ) 
    

    编辑:

    改为最大值(代码)+ 1,因此,如果没有缝隙可用,有可用的新代码。

    +0

    +1,正是我所要求的。 – Naved 2012-03-07 03:30:00

    相关问题