2016-06-13 6 views
0

Es ist den ganzen Tag, dass ich versuche, die Ursache eines seltsamen Fehlers herauszufinden.Rails: SQL-Abfrage lässt Produktionsserver für immer hängen

Ich habe diese Zeile Code in einem Modell (die durch eine Controller-Aktion aufgerufen wird):

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

Alles funktioniert wie erwartet (auf meinem lokalen Rechner, auf dem Produktionsserver und sogar mit Tausenden von Lieferungen).

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

Das auf meinem lokalen Rechner wie erwartet funktioniert auch mit Tausenden von Lieferungen:

Um Steigerung der Leistung Ich habe die obige Zeile mit roher SQL ersetzt. Jedoch auf meinem Produktionsserver (2 GB RAM/2 Kerne) diese zweite Version funktioniert nur, wenn ich ein paar Datensätze einfügen, sonst mit 2000 Lieferungen oder so hängt die Anfrage für immer.

Um genauer zu sein:

  • der Browser keine Antwort und die HTTP-Anforderung in der Datenbank folgenden hängt gespeichert
  • bekommt immer
  • die Lieferungen
  • die Linien die execute werden nie ausgeführt

Wenn ich eine dritte Version von Code verwende und ich das rohe SQL durch die Verwendung von activerecord-import Edelstein ersetze, bekomme ich genau den gleichen Fehler.

Was kann diesen Fehler verursachen?

Ich frage mich sogar, ob es die lange Ausgabe Nachricht generiert werden kann (die große SQL-Abfrage), die die Anwendung abstürzt (ich benutze logz.io).

+0

Warum sind Sie beteiligt Rails in das alles zu? Ein einfaches 'Insert in ... Select ...' Bit von SQL wäre ein besserer Startpunkt, oder? –

Antwort

0

Mein Verdächtiger war richtig.

Das Problem wird durch den Edelstein logstash-logger verursacht, wenn die Protokollnachricht zu lang ist.

Von der Schienen-Konsole konnte ich das Problem reproduzieren, und ich bekam (für eine Abfrage):

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] 
Verwandte Themen