我在程序里使用了select ...for update对oracle数据库中某条记录进行锁定,在调试程序的时候为了验证行锁的可行性,在对此条记录进行commit或rollback操作之前将程序停止,此时此记录应该是被锁定了,再次启动程序的时候,我期望的是当程序执行到select ...for update的时候会有记录被锁定的相应提示,但结果是程序执行的很顺利,没有任何异常;但另一方面,我用toad连接oracle,同时打开两个toad,在其一执行语句select ...for update,在commit之前,在另外一个toad里再次执行此条语句,会有错误提示:资源正忙...,这正是期望的结果。请问各位高手,为什么在程序里不能和toad里有一致的结果呢?

解决方案 »

  1.   


    你需要启动2个应用程序才行啊,你不都启动了2个toad客户端了嘛!
      

  2.   

    进行commit或rollback操作之前将程序停止,回话应该断了吧。
      

  3.   

    你程序启动后又停止了不就等于释放了锁了吗!
    你启动程序(假设为会话A)执行select xx from table where ... for update;将相应的行锁住;这时在另一程序中启动(假设为会话B)执行select xx from table where for update nowait;
    这样如果会话A锁住了那一行,会话B则会因为锁而立即给予提示信息不会处于等待状态!这时你可以看到你的程序的提示信息:resource busy and acquire with NOWAIT specified
      

  4.   

    被锁的记录,其他的会话也是能够执行select语句的啊
    如果是update语句,应该是不能执行的。不知道是不是LZ没有正确判断ora的报错(sqlca.sqlcode)?导致程序无任何异常(实际上已经报错)
      

  5.   

    程序里已经做了很明确的异常捕捉,不会有问题的。单纯的select语句无论在任何会话里都能执行无误,但这里的select语句是加了锁定的,就是select...for update...,仍然可以顺利执行且无任何异常
      

  6.   


    同意,你的程序退出的话,session结束,会自动rollback释放锁。
      

  7.   

    你说执行第一个客户端时,在没有commit或者rollback后,如果仍然没有断开第一个客户端的话,那仍然处于锁状态!
    第二个客户端启动后,是会被锁的!而你把第一个客户端停止了,当然已经把第一个客户端的锁给释放了啊!第二个客户端执行select 。。 for update当然不会被锁了
      

  8.   

    当然没有断开连接,任何一个客户端都在工作着,有个问题不明白,你们所说的连接和断开是指OracleConnection类里的open()和close()方法吗?我每处理一次数据库操作都会使用open()和close()方法。但客户端到服务器的连接始终保持着。行锁应该是基于会话的,程序里我使用的是ADO.NET,会不会跟连接池有关?请指点一二。
      

  9.   

    同意一楼的。
    这里的链接指的是程序中获取的数据库Connection,把程序停止时,这个线程结束了,相应的链接回收,行级锁同时也被释放。再次启动程序时属于正常的锁定。
      

  10.   


    估计和连接池有关.虽然ORACLE看到SESSION仍然存在,但是客户端其实已经CLOSE,虽然程序没有ROLLBACK, ORACLE会自动ROLLBACK. 建议你暂时屏蔽 close()方法来试验.泡这个版面的人,基本都是从纯粹ORACLE的角度谈问题.
      

  11.   

    select * from t for update 锁定(oracle锁都不会阻塞读),是不会阻塞读取数据的,也就是说即使你锁定这行数据,别的程序仍然可以读取 ,但不能修改
    这点oracle 和其它数据不一样
      

  12.   


    没有用asp.net,不过用过java,asp.net里有没有自动提交的设置了,java里是有的,setAutoCommit(true)就是自动提交了。不需要通过commit叻