ActiveRecord :: StatementInvalid: PG InFailedSqlTransaction

72

Ich versuche, ein ActiveRecord-Objekt zu erstellen. Beim Erstellen wird jedoch dieser Fehler angezeigt.

(0.1ms)  ROLLBACK
ActiveRecord::StatementInvalid: PG::InFailedSqlTransaction: ERROR:  current transaction is       aborted, commands ignored until end of transaction block

Irgendwelche Ideen Leute bezüglich des Problems.

untwal
quelle
Verwenden Sie PSQL mit einem Spaltentyp von json? Aktualisiere es auf PSQL 9.4 und benutze es jsonb. Problem gelöst!
Keime12
postgresql.org/docs/9.1/static/transaction-iso.html Dies ist das Hauptproblem, das wir hatten.
Bis zum

Antworten:

107

Keine der anderen Antworten behebt die Grundursache des Problems.

Das Problem ist, dass Postgres, wenn es eine Ausnahme auslöst, zukünftige Transaktionen auf derselben Verbindung vergiftet.

Das Update besteht darin, die betreffende Transaktion zurückzusetzen:

begin
  ActiveRecord...do something...
rescue Exception => e
  puts "SQL error in #{ __method__ }"
  ActiveRecord::Base.connection.execute 'ROLLBACK'

  raise e
end

Siehe Referenz .

B Sieben
quelle
1
Auch im Rails AR :: Transactions Handbuch erwähnt
Somazx
12
Bitte retten Sie nicht vor Exception, wie hier angegeben: stackoverflow.com/questions/10048173/… Ausnahme ist die Wurzel der Ausnahmehierarchie von Ruby. Wenn Sie also Ausnahme retten, retten Sie vor allem, einschließlich Unterklassen wie SyntaxError, LoadError und Interrupt.
Adantj
1
In dem Kommentar, in den ich den Link eingefügt habe, werden die Gründe für die Problematik Ihres Codes und teilweise schlechte Ratschläge deutlich angegeben. Der Link enthält auch zusätzliche Informationen. Dein "Warum nicht?" Kommentar macht keinen Sinn, es sei denn, Sie haben den Kommentar oder den Link oder beides nicht gelesen. Ich würde Ihnen dasselbe fragen, wenn Sie sich nicht die Zeit nehmen, über Ihre Fragen und Antworten nachzudenken, warum sollten Sie sie dann überhaupt posten?
Adantj
1
@adantj Es ist vollkommen in Ordnung, eine Ausnahme zu retten, wenn Sie sofort erneut erhöhen . wie in der gegebenen Antwort getan
Sampson Crowley
83

Ich hatte dieses Problem. Starten Sie einfach den Rails Server neu und es sollte funktionieren

Furkan Ayhan
quelle
7
Ich hatte gerade dieses Problem und ein Neustart des Servers hat es tatsächlich behoben. Hat jemand eine Erklärung für dieses Verhalten?
plu
1
Ich hatte das gleiche Problem in der Testumgebung (rspec löst den Fehler aus). rake db:drop+ rake db:create+ hat rake db:migratedas Problem gelöst. Vielleicht habe ich die Migration durcheinander gebracht.
Nobu
Testete in der Schienenkonsole. Das Neuladen war nicht ausreichend, um die Konsole neu zu starten. Vielen Dank!
Volte
Dies ist keine praktikable Lösung. Ein Neustart eines Servers ist keine Option, wenn ein Dienst autonom ausgeführt werden soll. Das Problem ist, dass sich die PG-Verbindung in einem fehlerhaften Zustand befindet und erneut verbunden werden muss oder ausgeführt werden muss, um ROLLBACKdie aktuelle Transaktion zu beenden.
Thesmart
Dies fiel mir nach dem Upgrade auf PG12 und Ruby 2.6.6 ein. Ich benutze rvm und das Upgrade auf 2.6.6 erforderte eine Neuerstellung des pg gem für das neue gemset. A rake db:test:preparehat nicht funktioniert - aber a hat RAILS_ENV=test rake db:drop db:create db:migratedas Problem gelöst.
Martin Streicher
15

Dieses Problem trat in meiner Testumgebung auf und wurde durch die Tatsache verursacht, dass jeder Test in eine eigene Transaktion eingeschlossen war.

Ich habe das Juwel database_cleaner verwendet und es so konfiguriert, dass Tests NICHT in eine Transaktion eingeschlossen werden, wenn sie Javascript verwenden. Um das Problem zu lösen, habe ich js: truezu jeder Spezifikation hinzugefügt , die dieses Problem verursacht hat. (Auch wenn in den Spezifikationen kein Javascript verwendet wurde, war dies der bequemste Weg, um sicherzustellen, dass die Tests nicht in eine Transaktion eingebunden werden. Ich bin mir jedoch sicher, dass es weniger hackartige Möglichkeiten gibt, dies zu tun.)

Als Referenz finden Sie hier die Datenbankdatenbank-Konfiguration von spec/support/database_cleaner.rb:

RSpec.configure do |config|

  config.before(:suite) do
    DatabaseCleaner.clean_with :deletion
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :deletion
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

end

Wenn Sie sich nicht mit database_cleaner sind, dann ist wahrscheinlich der Grund , warum die Tests in Transaktionen verpackenden würde wäre, dass die use_transactional_fixturesOption eingestellt ist truein spec/spec_helper.rb. Versuchen Sie es auf false zu setzen.

Teddy Widom
quelle
Wenn Sie Transaktions-Fixtures deaktivieren, ohne etwas wie DatabaseCleaner anzuschließen, sammelt Ihre Testdatenbank weiterhin Daten aus jedem Lauf. Anstatt js: truefür jede Spezifikation festzulegen, die nicht wie erwartet funktioniert, können Sie sie für Integrationsspezifikationen festlegen. Beachten Sie, dass die Verwendung von :deletionanstelle von :transactionviel langsamer ist. Daher sind Transaktionen nach Möglichkeit vorzuziehen.
Lobati
Bis zu diesem Punkt stellte ich fest, dass die zusätzliche Komplexität von DB-Reinigern im Gegensatz zu Standardtransaktionstests schwierig war (auch bekannt als mehr Fehler). Mein Problem war jedoch, dass ich zwei Anfragen wie get ...im selben itBlock hatte. Durch Verschieben wurde dieser Fehler behoben.
Ryan
Ich denke nicht, dass das Hinzufügen js: trueder beste Weg ist, um dieses Problem zu beheben. Das Problem wird dadurch nicht gelöst, und die Löschstrategie ist sehr langsam . Durch den Wechsel zur Transaktionsstrategie habe ich meine Tests um das 2,5-fache beschleunigt. Siehe meine Antwort unten.
B Seven
8

Sie können sehen, was wirklich im Postgresql-Protokoll vor sich geht. Ich verbringe viel Zeit damit, mich mit diesem Problem zu befassen, und finde schließlich heraus, dass wir Upsert Gem missbrauchen, um einen PG-Fehler zu verursachen. Nur im Postgresql-Protokoll haben Sie die wirklichen Informationen darüber, was los ist

https://github.com/seamusabshere/upsert/issues/39

William Herry
quelle
1
Der Link hat nicht viel geholfen, aber die Idee, die Postgres-Protokolle zu überprüfen, hat sich bewährt. In meinem Fall war es eine unvorbereitete Testdatenbank. Vielen Dank!
Mat Schaffer
6

Ich bin auf diesen Fehler gestoßen, wenn ich auf eine Spalte in meinen Spezifikationen verweise, die nicht mehr vorhanden ist. Stellen Sie sicher, dass Ihre Datenbank auf dem neuesten Stand ist und Ihr Code keine Spalte erwartet, die nicht vorhanden ist.

Lobati
quelle
3

Problem:

  1. Das Programm führt eine falsche SQL-Anweisung aus. Eine falsche SQL-Anweisung ist die Hauptursache des Problems.
  2. Das Programm rollt nicht sofort nach einer falschen SQL-Anweisung zurück oder gibt SAVEPOINT frei.
  3. Das Programm führt SQL-Anweisungen nach einer falschen SQL-Anweisung aus.
  4. PostgreSQL löst FEHLER aus: Die aktuelle Transaktion wird abgebrochen, Befehle werden bis zum Ende des Transaktionsblocks ignoriert

Lösung:

Suchen Sie eine falsche SQL-Anweisung und korrigieren Sie sie. Wenn Sie die SQL-Anweisung nicht korrigieren möchten, verwenden Sie nach einer falschen SQL-Anweisung ROLLBACK oder RELEASE SAVEPOINT.

John Doe
quelle
2

In meinem Fall habe ich diesen Fehler nur erhalten, weil ich meine Test-Datenbank nicht geharkt hatte.

nfriend21
quelle
2

In meinem Fall hatte die Postgres-Konfiguration bei /usr/local/var/postgres/postgresql.confden Datentyp als internationales Format vondmy

Durch Ändern des Datentyps in das amerikanische Format wurde mdydieses Problem für mich behoben.

Winsor
quelle
0

Hatte ein ähnliches Problem nach dem Upgrade von Rails von 4.2.2 auf 4.2.5 Ich musste Gem aktualisieren pgund das Problem trat auf

9) WorkPolicy#is_publicly_viewable? is publicly visible hides work if deleted
     Failure/Error: before { DatabaseCleaner.clean_with :deletion }
     ActiveRecord::StatementInvalid:
       PG::InFailedSqlTransaction: ERROR:  current transaction is aborted, commands ignored until end of transaction block
       :             SELECT tablename
                   FROM pg_tables
                   WHERE schemaname = ANY (current_schemas(false))

Teddy Widom Answer ist in diesem Sinne richtig, um das Problem zusammenzufassen:

Manchmal DatabaseCleaner.clean_with :deletionstören Sie bei der Verwendung möglicherweise die PostgreSQL-Transaktion.

Die Lösung für mich bestand also darin, DatabaseCleaner.clean_with :deletionTeile der Tests zu ersetzen, bei denen dies verursacht wurdeDatabaseCleaner.clean_with :truncation

Nur noch eine Sache, um Leute zu googeln. Wenn Sie diesen Stack-Trace bemerken:

An error occurred in an `after(:context)` hook.
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column "table_rows" does not exist
LINE 1: ...ion_schema.tables WHERE table_schema = 'test' AND table_rows...
^

... kann durch dieses Problem verursacht werden

Äquivalent8
quelle
0

Ich habe dieses Problem. Und ich fand heraus, dass es meine Frage war. Dies bedeutet, wenn ich mit Zuordnung abfrage, ohne eine Tabellenspalte anzugeben. Ex:

class Holiday < ApplicationRecord
     belongs_to :company
end

class Company < ApplicationRecord
    has_many :timeoffs
end

Im Urlaubsmodell frage ich ab

company.timeoffs.where("(start_date <= ? and end_date >= ?) and id != ?", begin_date, begin_date, 1)

Der Fehler tritt auf, weil ich nicht angegeben habe, welche Tabelle id für mich funktioniert hat, nachdem ich den Code in geändert habe

company.timeoffs.where("(start_date <= ? and end_date >= ?) and time_offs.id != ?", begin_date, begin_date, 1)
pdkpro
quelle