如有一个Balance字段,用来保存用户余额,程序中发现如果有2条语句同时更新这个字段的话,就会出现问题
update XXXX set Balance=Balance+'1000' 
update XXXX set Balance=Balance+'500' ,当然这2条更新语句都是在程序的不同地方
如果Balance的最初值是1000,第一条语句得到Balance的值,正要更新但是还没有更新,马上就该第2条语句执行了,它首先得到的值也是1000,而不是第一条语句更新后的2000,这个时候第一条语句执行更新了Balance的值是2000,然后第2条语句再执行更新,Balance的值就变成了1500了,而不是想要的2500,想请教各位大侠一下,有办法解决这一的问题吗?在执行第一条语句的时候,第2条检查到字段Balance正在被更新,就会阻塞,等到第一条被更新完毕以后再执行,不知道这样行不行!!!请教各位了!!!!!!

解决方案 »

  1.   

    我晕,ORACEL机制就是这样的如果第一个SQL在更新,就会锁表,第二个SQL会等待,
      

  2.   

    没那回事。你把oracle想得太弱了
      

  3.   

    去了解一些oracle事务,锁表相关的知识。oracle不是这样工作的。
      

  4.   

    按照2位的解答,应该不会出现这样的问题,但是我测试结果的确是这样的,会不会有这个原因呢
    我在这2个SQL语句前面都加了事物
    conn.setAutoCommit(false);
    update XXXX set Balance=Balance+'1000'  
    conn.setAutoCommit(true);
    conn.commit();
    conn.setAutoCommit(false);
    update XXXX set Balance=Balance+'500'  
    conn.setAutoCommit(true);
    conn.commit();
    第2条语句执行的时候,正好第一条还没有被提交,所以得到的值才会是1500
      

  5.   

    pstmt = conn.prepareStatement(this.strSQL);
    pstmt.executeUpdate();
    更新SQL语句的方法是绑定变量,executeUpdate执行
      

  6.   

    --For example
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    BEGIN TRANSACTION;
    UPDATE EMPLOYEE SET SALARY = SALARY + 1000 WHERE EMP_ID = 'XXX';
    -- ... some other scripts
    COMMIT;
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
      

  7.   

    我刚才按照你的方法试了,没有问题啊
    1.更新数据,等待提交
    2.另个一session,更新数据,发现记录被锁,等待
    3.commit第一个session,查询数据被更新
    4.commit第二个session,查询数据是根据3.提交之后的数据再次更新
    结果和楼主说的不一样,我的操作和楼主的操作过程不一样么?
      

  8.   

    因为oracle没有读锁 所以在事务一提交前 去读取Balance值就是原值1000
    不考虑效率的话
    可以在update XXXX set Balance=Balance+'1000之前运行
    select * from XXXX for update 打开锁则第二个语句 
    update XXXX set Balance=Balance+'500' 在第一个语句commit前运行就会报错
      

  9.   

    先使用select * from XXXX for update 将表锁定,
    然后update XXXX set Balance=Balance+'1000,这时候如果执行update XXXX set Balance=Balance+'500' 
    的话,update XXXX set Balance=Balance+'500' 会出现等待现象。
    等到update XXXX set Balance=Balance+'1000执行完成,执行commit之后,
    update XXXX set Balance=Balance+'500'才会执行。
      

  10.   

    oracle锁机制是只有在进行DML操作时才进行行级锁 ;写入器不堵塞读取器,读取不堵塞写入 所以会有并发和多版本的问题。  
    解决楼主问题
    在执行第一条语句的时候,第2条检查到字段Balance正在被更新,就会阻塞,等到第一条被更新完毕以后再执行;使用Select…For Update语句的语法 FOR UPDATE [NOWAIT]子句。
    该语句用来锁定特定的行(如果有where子句,就是满足where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被commit语句或rollback语句结束为止。