update users set balance=balance-100 where id=1 and  balance>=100可以保证本语句的原子性。 
但如果并发的时候,如果有其它程序也在操作则有可能出问题比如P1->   select balance into @X from users where id =1
    P2 -> update users set balance=balance-100 where id=1 and  balance>=100
P1 ->  update users set balance=@x-100 where id=1 

解决方案 »

  1.   

    update users set balance=balance-100 where id=1 and  balance>=100
    可以保证语句的原子性,关键如何在并发情况下保证结果不为负
    这就需要事物控制了。
      

  2.   


    非常感谢,我能 理解p1会出现问题,因为他where后面没有跟and  balance>=100,但如果我所有减去balance的update语句后面都写上and  balance>=100,那么是不是就算大并发下也不可能出现balance<100的时候执行这个update语句,期待您的回复
      

  3.   


    假设我整个项目中对只有这一句话对balance进行操作,是否可以保证balance不可能为负
    就是只有一句:update users set balance=balance-100 where id=1 and  balance>=100。期待您的回复,这个问题困扰我很久
      

  4.   

    update 操作时会加X锁的,你可这样操作,最好开始事务,如果有错,可以ROLLBACK,正常的话,COMMIT;
      

  5.   

    这样可以的
    但你也要对返回结果 affectrows 来判断是否有扣到
      

  6.   


    假设我整个项目中对只有这一句话对balance进行操作,是否可以保证balance不可能为负
    就是只有一句:update users set balance=balance-100 where id=1 and  balance>=100。期待您的回复,这个问题困扰我很久
    不能保证因为业务是在变化的不能不会出现,所以考虑事物处理。
      

  7.   


    对,我就是判断如果受影响的行数等于1,那就继续事务,然后如果为0,就直接返回了,因为balance肯定小于100了。不知道这样可以吗,排除其他语句,光这这个不可能出现小于100扣款的现象吧
      

  8.   


    假设我整个项目中对只有这一句话对balance进行操作,是否可以保证balance不可能为负
    就是只有一句:update users set balance=balance-100 where id=1 and  balance>=100。期待您的回复,这个问题困扰我很久
    不能保证因为业务是在变化的不能不会出现,所以考虑事物处理。排除其他语句,只运行这一条,就算大并发也不可能出现balance小于100的时候执行成功吧
      

  9.   


    非常感谢,我能 理解p1会出现问题,因为他where后面没有跟and  balance>=100,但如果我所有减去balance的update语句后面都写上and  balance>=100,那么是不是就算大并发下也不可能出现balance<100的时候执行这个update语句,期待您的回复这个跟加不加 and balance>=100关系不大,主要看是否在同一个事务中操作。
      

  10.   


    假设我整个项目中对只有这一句话对balance进行操作,是否可以保证balance不可能为负
    就是只有一句:update users set balance=balance-100 where id=1 and  balance>=100。期待您的回复,这个问题困扰我很久
    不能保证因为业务是在变化的不能不会出现,所以考虑事物处理。排除其他语句,只运行这一条,就算大并发也不可能出现balance小于100的时候执行成功吧大并发的时候,就是一个事务等待另外一个事务结束。
      

  11.   

    关于mysql库锁以及事务的理解,请参考:http://blog.itpub.net/26230597/viewspace-1315111/