3

我有一个我故意崩溃的rails应用程序..它是本地的,我只是按ctrl + c并在处理记录的中途杀死它..

在我看来,不应该提交块中的记录。这是 postgres“错误”还是 rails“错误”,还是 dave 错误?

      ActiveRecord::Base.transaction do
        UploadStage.where("id in (#{ids.join(',')})").update_all(:status => 2);

        records.each do |record|
          record.success = process_line(record.id, klas, record.hash_value).to_s[0..250]
          record.status = 1000
          record.save();
        end    
      end

我通过读取状态为 1 的所有记录来生成我的 ID。
除了这个函数将状态设置为 1000 之外,什么都没有。

如果操作因任何原因崩溃,我希望数据库中没有状态 = 2 的记录......但这不是我所看到的。一半的记录状态为 1000,另一半的状态为 2...。

我错过了什么吗?
如果应用程序崩溃,我如何确保没有 2?


编辑:
我发现这个链接 http://coderrr.wordpress.com/2011/05/03/beware-of-threadkill-or-your-activerecord-transactions-are-in-danger-of-being-partially-committed/

4

1 回答 1

1

正如我所怀疑的那样,正如 dave 的更新所证实的那样,在某些情况下,当你杀死一个线程时,ActiveRecord 似乎会提交一个半完成的事务。哇,安全!有关详细说明和缓解选项,请参阅dave 的链接

如果您正在模拟硬崩溃(主机操作系统崩溃或插拔),那么 control-C 绝对不是正确的方法。用于Control-\发送SIGQUIT通常不处理的 ,或用于kill -KILL硬杀进程而没有机会进行清理。Control-C发送SIGINT这是一个温和的信号,通常附加到一个干净的关闭处理程序。

一般来说,如果你正在调试这样的问题,你应该启用详细的查询日志并查看 Rails 正在做什么。使用log_statement = 'all'inpostgresql.conf然后检查 PostgreSQL 日志。

于 2012-12-12T00:25:16.313 回答