我现在有1至20 个客户端要访问oralce 数据一的同一张表 假设表为a但客户端是java写的程序   每个程序是要做的是从a中取出一条数据去处理,并修改下这条数据的状态怎么防止客户端取到同一条数据,重复处理用java 同步已经不可能,因为是多个JVM,没办法 控制同步在数据库方面有什么方法我想到的是select ...for update 
但用这个,假设一个客户端在处理取,另一个客户端也能取到同样的记录
???
有什么好方法

解决方案 »

  1.   

    使用select ...for update nowait
    此时 假设一个客户端在处理取,另一个客户端也能取到同样的记录,则立即报错,无须等待。
      

  2.   

    假定程序 是这样: 1 :String querySql  = select * from a for update ; //这样就取出来了
                     2: String updateSql = update  a set status = 60 马上我就把这样记录的状态可修改了
    但在这1 和2 语句 间,另一个客户端正在执行querySql 那这样就可能会取重复了啊
      

  3.   

    1  如果你select * from a for update ,则锁定所有记录。你想再update  a set status = 60 ,除非前面的事务提交,否则你想都别想!2 querySql有ORACLE一致性读要保证,不会读取在你发起query后才提交的数据。故你应该多看看ORACLE锁及UNDO部分的内容。
    我只是告诉你,不会发生你所说的情况,不过另外一个倒是可能,那就是死锁。
    死锁纯属业务逻辑问题,无论是数据库设计,还是程序逻辑,都要注意!
      

  4.   

    这样说select * from a for update 的话, 我后面就没办法修改状态 了,除非前面的事件提交或roolback了
    那就有什么办法解决这个问题 
      

  5.   

    select * from a for update本身就有问题。
    它是一个悲观锁,你把锁人工扩大了。一个事务里需要处理多少数据,就锁定多少数据。
    像你这样锁定整个表,本来就是你想独占此表,也就是exclusive方式。
    for update where ……
    仅锁顶你需要处理的记录,则其他记录可以被其他会话修改。
      

  6.   

    放在同一事务里?
    此时它们属于同一session,querySql可以看见本session的脏数据。
    我不知道你到底想实现什么功能,可否描述下你的需求?
      

  7.   

    客户端是 
    java 程序用jdbc 访问数据库 表a有0-20个客户端客户端要要做的就是取出a中状态为末处理的一条记录去分析,
    分析完成后,再把状态修改在处理成功
    如果同时访问 ,可能客户端会取到我是重复的数据
    比如说: client1 取了a中 id 为1的记录
             client2 也有可能会取到id 为 1的记录现在要解决就是防止客户端取重复的记录想到一个笨方法就是在a增加一个字段clinetId表示客户端的  client1...
    然后 client1 只取clientId为client1的记录
    client2 只取clientId为client2的记录....不知道还有什么好方法
      

  8.   

    有0-20个客户端 客户端要要做的就是取出a中状态为末处理的一条记录去分析, 
    分析完成后,再把状态修改在处理成功 每个客户端进入表后取记录,都只是根据status='末处理'来取吗?没有其他过滤条件?
    你在更新状态前,需要分析,需要时间,此时你只是分析该条记录,如果不锁定改记录,则其他client肯定可以修改甚至锁定之。
    在处理期间,锁定它先。这样防止你在分析期间,其他client也来处理它。
      

  9.   

    没有其它条件了
    就只根据status ='末处理'来取数据如果分析时锁定,其它client 不能取数据了所我想在再个字段clientId ,这样取数据时就status ='末处理' and clientId ='client1'
    这样可以解决
    还有没有其它可行的办法 
      

  10.   

    其实ORACLE加锁也就是你在update的那一小段时间里会加比如说某个员工select出了一条数据
    可能他要看个10分钟 再做决定
    而update肯能1秒钟就完成了可问题是在他看的10分钟内会不会有其他用户已经处理了这条记录了……
    呵呵 暂时没想出太好的办法
      

  11.   

    楼主过滤了,Oracle本身就有处理数据并发的能力
      

  12.   

    楼主用存储过程实现。
    存储过程第一句就是
    select ××,××,rowid from tble where status='未处理' and rownum =1 for update
    下面根据rowid来处理update。
      

  13.   

    假定程序 是这样: 1 :String querySql  = select * from a for update
      

  14.   

    恩……这个方法可以考虑一下
    使用rownum来进行限制
    不过最好加个排序 不然返回数据的顺序每次可能会有所不同 
    可是加了排序会不会变慢啊 呵呵 楼主自己根据实际情况权衡一下
      

  15.   

    java 读出数据库肯定做不到实时性。
    oracle的行级锁。应该不用考虑这些吧。