sql >> Databáze >  >> RDS >> PostgreSQL

PSQLException:aktuální transakce je přerušena, příkazy ignorovány až do konce bloku transakce

Tato chyba se mi zobrazila při použití Java a PostgreSQL při vkládání do tabulky. Ukážu vám, jak můžete tuto chybu reprodukovat:

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

Shrnutí:

Důvodem, proč se vám zobrazí tato chyba, je to, že jste zadali transakci a jeden z vašich SQL dotazů selhal a vy jste toto selhání zhltli a ignorovali. Ale to nestačilo, PAK jste použili stejné připojení pomocí STEJNÉ TRANSAKCE ke spuštění dalšího dotazu. Výjimka se vyvolá u druhého, správně vytvořeného dotazu, protože k další práci používáte nefunkční transakci. PostgreSQL vám v tom ve výchozím nastavení brání.

Používám: 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".

Můj ovladač PostgreSQL je: postgresql-9.2-1000.jdbc4.jar

Použití verze Java: Java 1.7

Zde je příkaz vytvoření tabulky pro ilustraci výjimky:

CREATE TABLE moobar
(
    myval   INT
);

Program Java způsobuje chybu:

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();
    }   

}

Výše uvedený kód mi vytváří tento výstup:

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

Řešení:

Máte několik možností:

  1. Nejjednodušší řešení:Neúčastněte se transakce. Nastavte connection.setAutoCommit(false); na connection.setAutoCommit(true); . Funguje to, protože pak je neúspěšný SQL ignorován jako neúspěšný příkaz SQL. Jste vítáni, když selžete SQL příkazy, jak chcete, a PostgreSQL vás nezastaví.

  2. Zůstaňte v transakci, ale když zjistíte, že první SQL selhal, transakci buď odvolejte/znovu spusťte, nebo potvrďte/restartujte transakci. Potom můžete pokračovat v selhání tolika SQL dotazů na tomto databázovém připojení, kolik chcete.

  3. Nezachycujte a ignorujte výjimku, která je vyvolána, když příkaz SQL selže. Poté se program zastaví na chybně naformátovaný dotaz.

  4. Získejte místo toho Oracle, Oracle nevyvolá výjimku, když selžete dotaz na připojení v rámci transakce a budete toto připojení nadále používat.

Na obranu rozhodnutí PostgreSQL dělat věci tímto způsobem... Oracle byl Díky tomu budete uprostřed měkcí, budete moci dělat hloupé věci a budete na to mít výhled.



  1. Relační vs. nerelační databáze – 1. část

  2. Jak nakonfigurovat SELinux pro systémy založené na MySQL (MySQL/MariaDB Replication + Galera)

  3. Jak dynamicky pivotovat s datem jako sloupcem

  4. Jak vygenerovat náhodné celé číslo v rozsahu v MariaDB