新手问题 请问为什么我的 ruby 在计算时会出现了奇怪的错误了!

QueXuQ · 2013年01月25日 · 最后由 QueXuQ 回复于 2013年01月25日 · 2690 次阅读

在本地一样的代码没有出问题,而在服务器上,除了一个奇怪的问题。 部分代码如下:

ActiveRecord::Base.transaction do
  @out_stock.pro_out_stocks.each do |pro_out_stock|
    stock_fitting = Stock.find_by_fitting_id(pro_out_stock.fitting_id)
    stock_fitting_amount = stock_fitting.amount - pro_out_stock.amount
    begin
      stock_fitting.update_attributes!(:amount => stock_fitting_amount)  #stock_fitting_amount<0会抛出异常
    rescue
      redirect_to :back
      return
    end
  end
end
redirect_to @out_stock

"#{stock_fitting_amount},#{stock_fitting.amount}, #{pro_out_stock.amount}" #然后我显示这些数据哪些出了问题,一看吓一跳。

#显示是这样:-1,-1, 1

也就是说,-1 - 1 = -1 为什么会出现这样的情况的呢? 可是我在显示`stock_fitting.amount 的页面看这个值是 1 的,怎么做减法的时候变成了 -1?

因为我必须确保,stock_fitting_amount >= 0,所以一但 stock_fitting_amount<0,update_attributes! 就会抛出异常,然后却在后面 return 了,采用 if 不会导致脏数据? 是否因为在事务里面,采用了 return,而导致脏数据的产生?

.amount 有调用 sql? 请求内缓存不?是不是脏数据?

#1 楼 @luikore 就我这句,算不算调用 sql?

Stock.find_by_fitting_id(pro_out_stock.fitting_id)

不了解怎么请求缓存,和脏数据。。请问有没有什么资料可以介绍看看呢。。 我发现整一个系统还真不是就像讲的那么简单。。

好吧 看走眼了……

#3 楼 @raven 嗯。这个确实是赋值,赋值之后,我去获取他们的值确是

"#{stock_fitting_amount},#{stock_fitting.amount}, #{pro_out_stock.amount}" 
#-1,-1, 1

估计问题像遗漏说的那样,stock_fitting.amount这个数据的问题,但是不知道怎么解决。

问题应该就在 amount 方法上……

#5 楼 @raven amountStock表里的一个字段。

除了@luikore 说的 你自己看看有没自定义 amount的读取方法吧

#7 楼 @raven 没有的,这个我发问题之前照过来了Model Stock里没有amount方法或者amount=()方法。 因为本地运行是没有问题的,服务器上运行也是没有问题的。 就是唯独在其中一个数据上面出现了我刚刚说的那个情况。 一百个数据里,就有出现了这样一个的错误。请问是怎么避免这种情况发生的。

没有主意了 从賍数据或缓存什么的找吧。或是你们数据库是读写分离的?祝好运~

10 楼 已删除

#10 楼 @dreamskyvt Mutex.new.synchronize??第一次看这个东东,是做什么用途的》?像这样说法,避免再次出现类似问题,涉及数据库的运算,都加这个? #9 楼 @raven 可以介绍几招怎么在脏数据里找不? 毫无头绪,找不到什么解决方法,客户那边又急,头都大了。

#11 楼 @QueXuQ 刚才写的不适合你这的情况,所以我给删了,问题肯定在于数据的脏读。打印的仅仅是脏掉的数据,对程序本身没有影响

脏数据在临时更新(脏读)中产生。事务A更新了某个数据项X,但是由于某种原因,事务A出现了问题,于是要把A回滚。但是在回滚之前,另一个事务B读取了数据项X的值(A更新后),A回滚了事务,数据项恢复了原值。事务B读取的就是数据项X的就是一个“临时”的值,就是脏数据。

按照这样说法估计是胀数据,我在贴些代码,看看这样写法是不是不对的,因为我在事务里加了 return。 @luikore @raven

#12 楼 @dreamskyvt 对程序有影响,所以我反复找是不是代码的问题,后面就尝试把数据读出来看看,结果就发现数据不正常。

#14 楼 @QueXuQ 你在执行之前也打印一条,然后再找原因

#15 楼 @dreamskyvt 谢谢,我现在部署不了,所以找不到原因,我晚上回去把改了的代码部署一下。看看是哪里的问题,刚刚有点头绪。

#16 楼 @QueXuQ 恩,数据不同步是个头疼的问题,祝你好运

每次取的 Stock.find_by_fitting_id(pro_out_stock.fitting_id) 会相同么

貌似有 3 方面的问题:


stock_fitting.amount 赋了 -1 应该是 update_attributes! 在更新数据库之前做的,因为 update_attribute 要调用 model 的 validation, 而 validation 需要新的值哦. 事务出错应该回滚,但是内存中模型属性人家不负责给你回滚的...

stock_fitting.reload
"#{stock_fitting_amount},#{stock_fitting.amount}, #{pro_out_stock.amount}"
# 是 -1, 0, 1 应该就对了

至于算出 -1 的原因,可能是 transaction 开始后,又卖出了一件?或者是 pro_out_stocks 里面对应两个相同的 fitting_id ? 出错然后回滚是正确的处理,但如果想少出错,可以优化一下 transaction, 或者加入一次重试


最后一个问题好像挺严重:你在 transaction 里面把异常吞了,事务回滚不了吧?rescue 最好在 transaction 外面做

#19 楼 @luikore 恩。谢谢。 请问在哪里加个“重试”比较好呢。 我找到了出问题的地方了,就是那个 return 把那个异常吞了。我重写了代码,就没有这样的问题了,可是重点是,我之前把异常吞了,导致事物回滚不了。很多数据都乱掉了,要一点点去查了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号