我有一个存储过程,其功能是通过select语句查找一个表A中是否有相应的记录,如果没有则进行插入操作,然后我用多个线程并发的去调用此存储过程,由于多个线程同时执行select语句,都以为表A中没有相应的记录,然后都去执行插入操作,造成重复插入,请教高手此问题如何解决?在线等!!!!!

解决方案 »

  1.   

    你可以用select ...  for update no wait语句 
      

  2.   

    使用select ...  for update no wait可以实现一个线程在读的时候其它的线程不能读吗?
      

  3.   

    那你只能像楼上说的那样,锁表了。
    no wait的话,一个线程锁住了,其他线程不等待,直接返回锁表失败。
      

  4.   

    是说一个线程锁住了,那么其他线程直接返回失败吗?有没有什么办法不让其它线程失败,而是让这些线程串行的执行这个存储过程,即第一个执行select语句的线程,在执行完insert之前,其它线程先不执行select呢?或是有什么其它方法,能让各个线程都能正确执行。
      

  5.   


    那就不要no wait,直接
    select * from table for update,锁住表,不commit,其他线程会一直等待。但要小心记得commit或rollback,要不就会死锁。
      

  6.   

    大致明白什么意思了,不过我还有一点点疑问,就是当一个线程执行select语句并进行锁定后,其它线程是在执行select之前就开始等呢,还是说执行select后发现被锁定了然后开始等?当解锁后其它线程是重新执行select语句吗?劳烦高手指教。
      

  7.   

    是执行select for update时发现表被锁就开始等。
    select并不是简单的一句话,在oracle的内部解析中其实分了很多步的。
      

  8.   

    十分感谢crazylaa,这里先结贴了,顺便问一句,解锁后其它线程会重新执行select读取数据吗?
      

  9.   

    会。
    比如
    A-》select * from tbl for update;锁住 表tbl,此时,B->select * from tbl for update,发现tbl被锁,开始等。
    A->commit; B->发现tbl被解锁,资源可用,继续执行sql。