PSQLException: transaksi saat ini dibatalkan, perintah diabaikan sampai akhir blok transaksi

152

Saya melihat stacktrace (terpotong) berikut di file server.log JBoss 7.1.1 Final:

Caused by: org.postgresql.util.PSQLException: 
ERROR: current transaction is aborted, commands ignored until end of 
transaction block

at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:374)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:302)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_23]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_23]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_23]
at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_23]
at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$StatementHandler.invoke(AbstractJdbc23PooledConnection.java:455)
at $Proxy49.executeUpdate(Unknown Source)   at org.jboss.jca.adapters.jdbc.WrappedStatement.executeUpdate(WrappedStatement.java:371)
at org.infinispan.loaders.jdbc.TableManipulation.executeUpdateSql(TableManipulation.java:154) [infinispan-cachestore-jdbc-5.1.2.FINAL.jar:5.1.2.FINAL]
... 154 more

Memeriksa file log Postgres mengungkapkan pernyataan berikut:

STATEMENT:  SELECT count(*) FROM ISPN_MIXED_BINARY_TABLE_configCache
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  CREATE TABLE ISPN_MIXED_BINARY_TABLE_configCache(ID_COLUMN VARCHAR(255) NOT NULL, DATA_COLUMN BYTEA, TIMESTAMP_COLUMN BIGINT, PRIMARY KEY (ID_COLUMN))
ERROR:  relation "ispn_mixed_binary_table_configcache" does not exist at character 22

Saya menggunakan Infinispan yang dikirim dengan JBoss 7.1.1 Final, yaitu 5.1.2.Final.

Jadi ini yang saya pikir sedang terjadi:

  • Infinispan mencoba menjalankan SELECT count(*)...pernyataan untuk melihat apakah ada catatan dalam ISPN_MIXED_BINARY_TABLE_configCache;
  • Postgres, untuk beberapa alasan, tidak menyukai pernyataan ini.
  • Infinispan mengabaikan ini dan membajak CREATE TABLEpernyataan itu.
  • Postgres barfs karena masih menganggap itu transaksi yang sama, yang gagal dibatalkan oleh Infinispan, dan transaksi ini diambil dari SELECT count(*)...pernyataan pertama .

Apa arti kesalahan ini dan ide bagaimana mengatasinya?

Jimidy
sumber
Hanya jika Anda datang ke sini seperti saya mencari di atas PSQLException: current transaction is aborted...( 25P02) dan mungkin juga JPAatau Hibernate. Akhirnya itu karena penggunaan Logback (baik!) Kami yang diumpankan dengan toString()objek DAO yang kelebihan muatan yang menyebabkan kesalahan dan tertelan dengan baik (tapi tidak disadari oleh saya): log.info( "bla bla: {}", obj )diproduksi bla bla: [FAILED toString()]. mengubahnya log.info( "bla bla: {}", String.valueOf( obj )menjadi nol-aman, tetapi tidak menelannya dan dengan demikian membiarkan transaksi terbuka gagal pada kueri yang tidak terkait.
Andreas Dietrich
Saya mendapatkan jenis kesalahan yang sama. Saya harus melepaskan koneksi sebelum sql. Kode saya adalah connection.commit ()
md. ariful ahsan

Jawaban:

203

Saya mendapatkan kesalahan ini menggunakan Java dan postgresql melakukan penyisipan pada tabel. Saya akan menggambarkan bagaimana Anda dapat mereproduksi kesalahan ini:

org.postgresql.util.PSQLException: ERROR: 
current transaction is aborted, commands ignored until end of transaction block

Ringkasan:

Alasan Anda mendapatkan kesalahan ini adalah karena Anda telah memasukkan transaksi dan salah satu dari SQL Queries Anda gagal, dan Anda menelan kegagalan itu dan mengabaikannya. Tapi itu tidak cukup, MAKA Anda menggunakan koneksi yang sama, menggunakan TRANSAKSI SAMA untuk menjalankan kueri lain. Pengecualian dilemparkan pada kueri kedua yang dibentuk dengan benar karena Anda menggunakan transaksi yang rusak untuk melakukan pekerjaan tambahan. Postgresql secara default menghentikan Anda dari melakukan ini.

Saya menggunakan: PostgreSQL 9.1.6 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2), 64-bit".

Driver postgresql saya adalah: postgresql-9.2-1000.jdbc4.jar

Menggunakan versi java: Java 1.7

Berikut adalah tabel membuat pernyataan untuk menggambarkan Pengecualian:

CREATE TABLE moobar
(
    myval   INT
);

Program Java menyebabkan kesalahan:

public void postgresql_insert()
{
    try  
    {
        connection.setAutoCommit(false);  //start of transaction.

        Statement statement = connection.createStatement();

        System.out.println("start doing statement.execute");

        statement.execute(
                "insert into moobar values(" +
                "'this sql statement fails, and it " +
                "is gobbled up by the catch, okfine'); ");

        //The above line throws an exception because we try to cram
        //A string into an Int.  I Expect this, what happens is we gobble 
        //the Exception and ignore it like nothing is wrong.
        //But remember, we are in a TRANSACTION!  so keep reading.

        System.out.println("statement.execute done");

        statement.close();

    }
    catch (SQLException sqle)
    {
        System.out.println("keep on truckin, keep using " +
                "the last connection because what could go wrong?");
    }

    try{
        Statement statement = connection.createStatement();

        statement.executeQuery("select * from moobar");

        //This SQL is correctly formed, yet it throws the 
        //'transaction is aborted' SQL Exception, why?  Because:
        //A.  you were in a transaction.
        //B.  You ran a sql statement that failed.
        //C.  You didn't do a rollback or commit on the affected connection.

    }
    catch (SQLException sqle)
    {
        sqle.printStackTrace();
    }   

}

Kode di atas menghasilkan output ini untuk saya:

start doing statement.execute

keep on truckin, keep using the last connection because what could go wrong?

org.postgresql.util.PSQLException: 
  ERROR: current transaction is aborted, commands ignored until 
  end of transaction block

Penanganan masalah:

Anda punya beberapa pilihan:

  1. Solusi paling sederhana: Jangan melakukan transaksi. Setel connection.setAutoCommit(false);ke connection.setAutoCommit(true);. Berhasil karena SQL gagal hanya diabaikan sebagai pernyataan sql gagal. Anda dipersilakan untuk gagal pernyataan sql semua yang Anda inginkan dan postgresql tidak akan menghentikan Anda.

  2. Tetap melakukan transaksi, tetapi ketika Anda mendeteksi bahwa sql pertama gagal, kembalikan / mulai kembali atau komit / mulai ulang transaksi. Kemudian Anda dapat terus gagal sebanyak kueri sql pada koneksi database yang Anda inginkan.

  3. Jangan menangkap dan mengabaikan Pengecualian yang dilemparkan ketika pernyataan sql gagal. Kemudian program akan berhenti pada kueri yang salah bentuk.

  4. Dapatkan Oracle sebagai gantinya, Oracle tidak mengeluarkan pengecualian ketika Anda gagal permintaan pada koneksi dalam transaksi dan terus menggunakan koneksi itu.

Dalam membela keputusan postgresql untuk melakukan hal-hal dengan cara ini ... Oracle telah membuat Anda lembut di membiarkan tengah Anda melakukan hal-hal bodoh dan menghadap itu.

Eric Leschinski
sumber
10
Lol @ Opsi 4 ... Saya telah melakukan cukup banyak pengembangan di Oracle, dan baru-baru ini mulai menggunakan Postgres ... benar-benar menyebalkan bahwa Postgres melakukan ini, dan sekarang kita harus benar-benar menulis ulang sebagian besar program kami yang kami porting dari Oracle ke Postgres. Mengapa tidak ada opsi seperti yang pertama untuk membuatnya berperilaku seperti Oracle tetapi tanpa komit otomatis ?
ADTC
2
Ditemukan setelah beberapa percobaan bahwa Opsi 2 adalah yang terdekat dengan perilaku Oracle. Jika Anda perlu mengeluarkan beberapa pembaruan, dan satu kegagalan tidak harus berhenti update berikutnya, hanya panggilan rollback()pada Connectionsaat SQLExceptiontertangkap. [ Pokoknya saya menyadari ini sejalan dengan filosofi PostgreSQL yang memaksa pengguna untuk membuat semuanya eksplisit, sedangkan Oracle memiliki filosofi untuk secara implisit mengurus banyak hal.]
ADTC
2
Opsi 2 berisi cabang mustahil or commit/restart the transaction. Seperti yang saya lihat tidak ada cara untuk melakukan setelah pengecualian. Ketika saya mencoba melakukan - PostgreSQL dorollback
turbanoff
1
Saya dapat mengkonfirmasi masalah yang diangkat oleh @turbanoff. Ini juga dapat direproduksi langsung dengan psql. (1) memulai transaksi, (2) menerbitkan beberapa pernyataan yang valid, (3) menerbitkan pernyataan yang tidak valid, (4) komit -> psql akan mengembalikan daripada melakukan.
Alphaaa
1
postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl diskusi menarik tentang topik ini. Jika masalah ini dipicu oleh pelanggaran kendala, para pengembang PostgreSQL merekomendasikan untuk memeriksa konflik sebelumnya (permintaan sebelum pembaruan / masukkan) atau gunakan savepointsuntuk memutar kembali ke titik sebelum pembaruan / masukkan. Lihat stackoverflow.com/a/28640557/14731 untuk kode sampel.
Gili
27

Periksa output sebelum pernyataan yang menyebabkannya current transaction is aborted. Ini biasanya berarti bahwa basis data melemparkan pengecualian bahwa kode Anda telah diabaikan dan sekarang mengharapkan permintaan berikutnya untuk mengembalikan beberapa data.

Jadi sekarang Anda memiliki ketidakcocokan antara aplikasi Anda, yang menganggap semuanya baik-baik saja, dan database, yang mengharuskan Anda untuk mengembalikan dan memulai kembali transaksi Anda dari awal.

Anda harus menangkap semua pengecualian dan transaksi rollback dalam kasus tersebut.

Ini masalah yang serupa.

vyegorov
sumber
Itu hebat, kecuali dalam kasus ini adalah Infinispan, perpustakaan pihak ke-3, yang berbicara dengan Postgres, dan bukan kode saya.
Jimidy
Nah, situasinya masih sama - transaksi harus dibatalkan. Mungkin memeriksa apakah ada versi terbaru dari perpustakaan yang Anda gunakan atau naikkan masalah dalam pelacak bug mereka. Jika Anda akan menemukan persis SQLyang menyebabkan masalah, Anda akan memiliki beberapa bidang untuk menghilangkan masalah menggunakan ekstensibilitas PostgreSQL.
vyegorov
Sepertinya Anda telah mengkonfirmasi kecurigaan saya - saya akan melihat sumber Infinispan 5.1.2 sekarang.
Jimidy
Agar adil, di kelas TableManipulation, ada try-catch di sekitar upaya untuk menjalankan pilih count (*) .... Mungkin driver Postgres tidak melempar salah satu pengecualian yang diharapkan. Saya akan menghubungkan debugger ke JBoss untuk mencoba mencari tahu lebih lanjut.
Jimidy
Kode Infinispan yang dimaksud disarankan dalam bug ini: issues.jboss.org/browse/... Saya telah melampirkan debugger untuk menjalankannya pada instance JBoss 7.1.1 langsung dan Postgres mengeluarkan pengecualian di tempat yang tepat. Mungkin itu adalah pernyataan JdbcUtil.safeClose () yang tidak melakukan pekerjaan mereka. Saya akan membesarkannya dengan Infinispan.
Jimidy
13

Saya pikir solusi terbaik adalah menggunakan java.sql.Savepoint.

Sebelum menjalankan kueri yang dapat melempar SQLException menggunakan metode Connection.setSavepoint () dan jika pengecualian akan dibuang, Anda hanya mengembalikan ke savepoint ini, tidak mengembalikan semua transaksi.

Kode contoh:

Connection conn = null;
Savepoint savepoint = null;
try {
    conn = getConnection();
    savepoint = conn.setSavepoint();
    //execute some query
} catch(SQLException e) {
    if(conn != null && savepoint != null) {
        conn.rollback(savepoint);
    }
} finally {
   if(conn != null) {
      try {
          conn.close();
      } catch(SQLException e) {}

   }
}
Michał Orliński
sumber
Saya sengaja turun entah bagaimana, hanya memperhatikan saja. Tidak disengaja, saya tidak dapat membatalkan kecuali jawaban diedit.
cerberos
Cara savepoint adalah solusi yang sebenarnya. Bekerja untuk saya juga di lingkungan PHP, Doctrine2 dan Postgres (9.5). Terima kasih
helvete
6

Sudah ada beberapa pekerjaan yang dilakukan pada driver JDBC postgresql, terkait dengan perilaku ini:
lihat https://github.com/pgjdbc/pgjdbc/pull/477

Sekarang dimungkinkan, dengan mengatur

autosave = selalu
dalam koneksi (lihat https://jdbc.postgresql.org/documentation/head/connect.html ) untuk menghindari sindrom 'transaksi saat ini dibatalkan'.
Overhead karena menangani savepoint di sekitar eksekusi pernyataan dijaga sangat rendah (lihat tautan di atas untuk detail).

thierry masson
sumber
5

Di Ruby on Rails PG, saya telah membuat migrasi, memigrasikan DB saya, tetapi lupa untuk me-restart server pengembangan saya. Saya me-restart server saya dan berhasil.

mantra
sumber
Itu juga kasus saya. Kupikir itu sesuatu yang bodoh, karena aku tidak benar-benar mencoba melakukan sesuatu yang rumit.
Tashows
4

Alasan untuk kesalahan ini adalah bahwa ada database lain sebelum operasi yang salah menyebabkan operasi database saat ini tidak dapat dilakukan (saya menggunakan terjemahan google untuk menerjemahkan bahasa Mandarin saya ke bahasa Inggris)

管 浩浩
sumber
2

Masalah telah diperbaiki di Infinispan 5.1.5.CR1: ISPN-2023

Dan Berindei
sumber
2

Anda perlu kembalikan. Driver JDBC Postgres sangat buruk. Tetapi jika Anda ingin menjaga transaksi Anda, dan hanya mengembalikan kesalahan itu, Anda dapat menggunakan savepoints:

try {
_stmt = connection.createStatement();
_savePoint = connection.setSavepoint("sp01");
_result = _stmt.executeUpdate(sentence) > 0;
} catch (Exception e){
 if (_savePoint!=null){
 connection.rollback(_savePoint);
}
}

Baca lebih lanjut di sini:

http://www.postgresql.org/docs/8.1/static/sql-savepoint.html

Mariano L
sumber
2

Saya memiliki masalah yang sama tetapi kemudian menyadari ada tabel dengan nama yang sama di database. Setelah menghapus itu saya bisa mengimpor file.

S.Perera
sumber
Ini adalah masalah saya, tabel untuk saya ada di dua skema yang berbeda.
tomat
0

Ini adalah perilaku PostgreSQL yang sangat aneh, bahkan tidak "sejalan dengan filosofi PostgreSQL yang memaksa pengguna untuk membuat semuanya eksplisit" - karena pengecualian ditangkap dan diabaikan secara eksplisit. Jadi bahkan pertahanan ini tidak berlaku. Oracle dalam hal ini berperilaku lebih ramah pengguna dan (seperti saya) dengan benar - ia meninggalkan pilihan bagi pengembang.

al0
sumber
0

Ini bisa terjadi jika Anda kehabisan ruang disk pada volume.

gregb
sumber
Saya menyadari ini bukan penyebab paling umum, tetapi ini adalah kasus di server yang saya diminta untuk memecahkan masalah. Jadi saya pikir ini harus dicantumkan sebagai penyebab potensial.
gregb
0

Saya hanya menemui kesalahan yang sama. Saya bisa mengetahui penyebab root dengan mengaktifkan log_statement dan log_min_error_statement di PostgreSQL lokal saya.

Saya mereferensikan ini

virtualpathum
sumber
0

Saya menggunakan JDBI dengan Postgres, dan mengalami masalah yang sama, yaitu setelah pelanggaran beberapa kendala dari pernyataan transaksi sebelumnya, pernyataan berikutnya akan gagal (tetapi setelah saya menunggu sebentar, katakanlah 20-30 detik, masalahnya hilang ).

Setelah beberapa penelitian, saya menemukan masalahnya adalah saya melakukan transaksi "secara manual" di JDBI saya, yaitu saya melingkupi pernyataan saya dengan BEGIN; ... COMMIT; dan ternyata pelakunya!

Di JDBI v2, saya bisa menambahkan penjelasan @Transaction, dan pernyataan dalam @SqlQuery atau @SqlUpdate akan dieksekusi sebagai transaksi, dan masalah yang disebutkan di atas tidak terjadi lagi!

Qinwei Gong
sumber
0

Dalam kasus saya, saya mendapatkan kesalahan ini karena file saya rusak. Sementara iterasi catatan file itu memberi saya kesalahan yang sama.

Mungkin di masa depan itu akan membantu siapa saja. Itulah satu-satunya alasan untuk mengirim jawaban ini.

Bharti Rawat
sumber
0

Saya menggunakan pegas dengan @Transactionalanotasi, dan saya menangkap pengecualian dan untuk beberapa pengecualian saya akan mencoba lagi 3 kali.

Untuk posgresql, ketika mendapat pengecualian, Anda tidak dapat menggunakan koneksi yang sama untuk melakukan lagi. Anda harus mengembalikan terlebih dahulu.

Untuk kasus saya, saya menggunakan DatasourceUtilsuntuk mendapatkan koneksi saat ini dan menelepon connection.rollback()secara manual. Dan panggilan metode ini direkrut untuk mencoba lagi.

ysjiang
sumber
0

Saya bekerja dengan spring boot jpa dan diperbaiki dengan menerapkan @EnableTransactionManagement

File yang dilampirkan dapat membantu Anda.masukkan deskripsi gambar di sini

Shahid Hussain Abbasi
sumber
0

Saya bekerja dengan spring boot jpa dan diperbaiki dengan menerapkan @EnableTransactionManagement

File yang dilampirkan dapat membantu Anda.

Shahid Hussain Abbasi
sumber
0

Coba ini COMMIT;

Saya menjalankannya di pgadmin4. Ini mungkin membantu. Ini ada hubungannya dengan perintah sebelumnya yang berhenti sebelum waktunya

Phillip Kigenyi
sumber
-1

Ubah tingkat isolasi dari baca berulang menjadi baca yang dilakukan.

ericj
sumber
-1

Set conn.setAutoCommit (false) ke conn.setAutoCommit (true)

Melakukan transaksi sebelum memulai yang baru.

abinash sahoo
sumber