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



我花了一整天的时间试图找出一个奇怪错误的原因。

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

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

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

为了提高性能我用原始SQL:替换了上面的行

# 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(', ')}")

即使有数千次交付,这在我的本地机器上也能正常工作。但是,在我的生产服务器上(2GB RAM/2核)第二个版本只有在我有几条记录要插入时才有效,否则在2000次交付左右时,请求将永远挂起

更准确地说:

  • 浏览器没有得到响应并且HTTP请求永远挂起
  • 交付保存在数据库中
  • execute后面的行永远不会执行

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

是什么导致了这个错误?

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

我的嫌疑犯是对的。

当日志消息过长时,问题是由logstash-loggergem引起的。

从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]

最新更新