Rails:SQL查询使生产服务器永远挂起

时间:2016-06-13 16:03:52

标签: ruby-on-rails postgresql rails-activerecord

我整天想弄清楚一个奇怪的错误的原因。

我在模型中有这行代码(由控制器动作调用):

PUT /attask/api/v4.0/user/[userID]?&sessionID=[sessionID]&updates=
{
    reservedTimes: 
        [ 
            { 
                "ID": "547debb6000dea62198bd66b7c73e174", 
                "objCode": "RESVT",
                "endDate": "2014-07-08T23:59:00:163-0600",
                "startDate": "2014-07-08T00:00:00:163-0600" 
            }, 
            { 
                "ID": "547debb6000dea61b8c695ba24918fe8",
                "objCode": "RESVT",
                "endDate": "2014-02-13T23:59:00:329-0700",
                "startDate": "2014-02-13T00:00:00:329-0700" 
            },
            { 
                "objCode": "RESVT", 
                "endDate": "2014-02-14T23:59:00:329-0700", 
                "startDate": "2014-02-14T00:00:00:329-0700" 
            } 
        ] 
} 

一切都按预期工作(在我的本地机器上,在生产服务器上,甚至数千次交付)。

为了提升性能,我已用原始SQL替换了上述行:

# it always works
self.deliveries.create(subscriptions.pluck('DISTINCT endpoint').collect {|e| {endpoint: e}})

即使有数千次交付,这也可以在我的本地机器上正常运行。但是在我的生产服务器上(2GB内存/ 2个内核)这个第二个版本仅在我要插入一些记录时才有效,否则2000个交付时左右请求会永久挂起

更确切地说:

  • 浏览器未收到回复且HTTP请求永远挂起
  • 在数据库中保存
  • # it hangs forever on the production server if you have many deliveries inserts = subscriptions.pluck('DISTINCT endpoint').collect do |e| "(#{self.id}, #{ActiveRecord::Base::sanitize(e)})" end ActiveRecord::Base.connection.execute("INSERT INTO deliveries (notification_id, endpoint) VALUES #{inserts.join(', ')}") 后面的行永远不会执行

如果我使用第三版代码并使用 activerecord-import gem替换原始SQL,我会得到完全相同的错误。

导致此错误的原因是什么?

我甚至想知道是否可能是生成的长输出消息(大型sql查询)导致应用程序崩溃(我使用logz.io)。

1 个答案:

答案 0 :(得分:0)

我怀疑是对的。

当日志消息太长时,问题是由logstash-logger gem引起的。

从rails控制台我可以重现这个问题,我得到了(对于一个查询):

LogStashLogger::Device::UDP - Errno::EMSGSIZE - Message too long
LogStashLogger::Device::UDP - Errno::EMSGSIZE - Message too long
LogStashLogger::Device::UDP - Errno::EMSGSIZE - Message too long
LogStashLogger::Device::UDP - Errno::EMSGSIZE - Message too long
... [and many many more]