PSQLException : 현재 트랜잭션이 중단되고 트랜잭션 블록이 끝날 때까지 명령이 무시됩니다.


152

JBoss 7.1.1 Final의 server.log 파일에 다음 (잘린) 스택 추적이 표시됩니다.

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

Postgres 로그 파일을 검사하면 다음과 같은 내용이 나타납니다.

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

JBoss 7.1.1 Final과 함께 제공되는 Infinispan을 사용하고 있습니다.

이것이 내가 생각하는 것입니다.

  • Infinispan SELECT count(*)...ISPN_MIXED_BINARY_TABLE_configCache;에 레코드가 있는지 확인하기 위해 명령문 을 실행하려고 시도 합니다 .
  • 어떤 이유로 Postgres는이 진술을 좋아하지 않습니다.
  • Infinispan은이를 무시하고 CREATE TABLE진술을 진행 합니다.
  • Postgres Barfs는 여전히 Infinispan이 롤백하지 못한 동일한 트랜잭션이라고 생각하기 때문에이 트랜잭션은 첫 번째 SELECT count(*)...명령문에서 시작됩니다.

이 오류는 무엇을 의미하며 어떻게 해결할 수 있습니까?


당신이 나처럼 위의 PSQLException: current transaction is aborted...( 25P02) 및 아마도 JPA또는을 검색하는 것처럼 여기에 온다면 Hibernate. 마지막으로 우리의 (! 좋은) 때문 Logback의 이 공급 사용 toString(): 오류의 원인 및 (나에 의해서가 아니라 accidentially 주목) 잘 삼켜 -overloaded DAO 객체 log.info( "bla bla: {}", obj )생성 bla bla: [FAILED toString()]. log.info( "bla bla: {}", String.valueOf( obj )그것을 null 안전으로 변경 했지만 삼키지 않고 관련없는 쿼리에서 트랜잭션을 열어 두지 않습니다.
Andreas Dietrich

같은 유형의 오류가 발생했습니다. SQL 전에 연결을 해제해야했습니다. 내 코드는 connection.commit ()
md입니다. ariful ahsan

답변:


203

Java와 postgresql을 사용하여 테이블에 삽입하는 동안이 오류가 발생했습니다. 이 오류를 재현하는 방법을 설명하겠습니다.

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

요약:

이 오류가 발생하는 이유는 트랜잭션을 입력했고 SQL 쿼리 중 하나가 실패하여 해당 오류를 파악하여 무시했기 때문입니다. 그러나 충분하지 않은 경우 동일한 트랜잭션을 사용하여 동일한 트랜잭션을 사용하여 다른 쿼리를 실행했습니다. 추가 작업을 수행하기 위해 손상된 트랜잭션을 사용하고 있기 때문에 올바르게 구성된 두 번째 쿼리에서 예외가 발생합니다. Postgresql은 기본적 으로이 작업을 중지합니다.

나는 사용하고있다 : 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".

내 postgresql 드라이버는 다음과 같습니다 postgresql-9.2-1000.jdbc4.jar

자바 버전 사용하기 : Java 1.7

다음은 예외를 설명하기위한 테이블 작성 명령문입니다.

CREATE TABLE moobar
(
    myval   INT
);

Java 프로그램이 오류를 발생시킵니다.

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

}

위의 코드는이 출력을 생성합니다.

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

해결 방법 :

몇 가지 옵션이 있습니다.

  1. 가장 간단한 해결책 : 거래하지 마십시오. (가) 설정 connection.setAutoCommit(false);connection.setAutoCommit(true);. 실패한 SQL은 실패한 SQL 문으로 무시되기 때문에 작동합니다. 당신은 당신이 원하는 모든 SQL 문을 실패 할 수 있으며 postgresql은 당신을 멈추지 않을 것입니다.

  2. 트랜잭션 상태를 유지하지만 첫 번째 SQL이 실패한 것을 감지하면 트랜잭션 롤백 / 다시 시작 또는 커밋 / 다시 시작 그런 다음 해당 데이터베이스 연결에서 원하는만큼 SQL 쿼리를 계속 실패 할 수 있습니다.

  3. sql 문이 실패 할 때 발생하는 예외를 포착하고 무시하지 마십시오. 그런 다음 잘못된 쿼리에서 프로그램이 중지됩니다.

  4. 대신, Oracle은 트랜잭션 내의 연결에서 쿼리에 실패하고 해당 연결을 계속 사용할 때 예외를 발생시키지 않습니다.

이 방법으로 postgresql의 결정을 방어하면서 오라클 중간에 부드러워서 바보 같은 일을하고 간과했습니다.


10
Lol @ Option 4 ... Oracle에서 상당히 많은 개발을 수행했으며 최근 Postgres를 사용하기 시작했습니다 ... Postgres 가이 작업을 수행하는 것은 정말 짜증나고 이제는 우리가 실제로 우리 프로그램의 큰 부분을 다시 작성해야합니다 Oracle에서 Postgres로 포팅 중입니다. 왜 자동 커밋없이 Oracle처럼 동작하도록하는 옵션 없는가?
ADTC September

2
몇 번의 시험 후 옵션 2 가 Oracle 행동에 가장 근접한 것으로 나타 났습니다 . 여러 업데이트를 발행해야하는데 한 번의 실패로 인해 후속 업데이트가 중지되지 않아야 rollback()하는 Connection경우 SQLException를 발견 하면 됩니다 . [ 어쨌든 . 나는이 인라인 오라클은 암시 적으로 많은 것들을 돌보는의 철학을 가지고있는 반면, 명시 적으로 모든 것을 확인하기 위해 사용자를 강제 PostgreSQL의 철학이다 실현]
ADTC

2
옵션 2 에는 불가능한 분기가 or commit/restart the transaction있습니다. 내가 볼 수 있듯이 예외 후에 커밋 할 방법이 없습니다. 내가 커밋하려고 할 때 rollback
-PostgreSQL

1
@turbanoff가 제기 한 문제를 확인할 수 있습니다. 또한로 직접 재현 할 수 있습니다 psql. (1) 트랜잭션을 시작합니다. (2) 유효한 명령문을 발행합니다. (3) 잘못된 명령문을 발행합니다. (4) commit-> psql은 커밋하지 않고 롤백합니다.
Alphaaa

1
postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl 이 주제에 대한 흥미로운 토론. 제약 조건 위반으로 인해이 문제가 발생하면 PostgreSQL 개발자는 사전 충돌 (업데이트 / 삽입 전 쿼리)을 확인하거나 savepoints업데이트 / 삽입 전 지점으로 롤백 하는 데 사용하는 것이 좋습니다 . 샘플 코드는 stackoverflow.com/a/28640557/14731 을 참조하십시오 .
길리

27

발생 된 명령문 전에 출력을 점검하십시오 current transaction is aborted. 이것은 일반적으로 데이터베이스에서 코드에서 무시하고 다음 쿼리에서 일부 데이터를 반환 할 것으로 예상하는 예외를 발생 시켰음을 의미합니다.

따라서 이제 응용 프로그램과 상태가 양호하다고 생각되는 응용 프로그램과 처음부터 트랜잭션을 롤백하고 다시 시작 해야하는 상태가 일치하지 않습니다.

이 경우 모든 예외와 롤백 트랜잭션을 포착해야합니다.

비슷한 문제가 있습니다.


이 경우를 제외하고는 제 코드가 아닌 Postgres와 대화하는 타사 라이브러리 인 Infinispan 일 것입니다.
Jimidy

상황은 여전히 ​​동일합니다. 트랜잭션을 롤백해야합니다. 최신 버전의 라이브러리가 있는지 확인하거나 버그 추적기 내에 문제를 일으킬 수 있습니다. SQL문제를 일으킨 정확한 부분 을 발견하면 PostgreSQL 확장 성을 사용하여 문제를 제거 할 수있는 필드가 있습니다.
vyegorov

내 의심을 확인한 것 같습니다. 이제 Infinispan 5.1.2 소스를 살펴 보겠습니다.
Jimidy

공정하게 말하자면, TableManipulation 클래스에는 select count (*) ... 실행 시도 주위에 try-catch가 있습니다. 아마도 Postgres 드라이버가 예상되는 예외 중 하나를 throw하지 않을 것입니다. JBoss에 디버거를 연결하여 자세한 내용을 알아 보려고합니다.
Jimidy

문제의 Infinispan 코드는 다음 버그에서 제안되었습니다 : issues.jboss.org/browse/… 라이브 JBoss 7.1.1 인스턴스에서 실행되는 디버거를 부착했으며 Postgres가 올바른 위치에서 예외를 발생시킵니다. 아마도 작업을 수행하지 않는 JdbcUtil.safeClose () 문일 것입니다. Infinispan으로 제기하겠습니다.
Jimidy

13

가장 좋은 해결책은 java.sql.Savepoint를 사용하는 것입니다.

SQLException을 발생시킬 수있는 쿼리를 실행하기 전에 Connection.setSavepoint () 메소드를 사용하고 예외가 발생하면이 저장 점으로 롤백 만하면 모든 트랜잭션이 롤백되지 않습니다.

예제 코드 :

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) {}

   }
}

나는 우연히 눈에 띄게 하향 공세했다. 의도적이지 않았으므로 답변을 편집하지 않으면 취소 할 수 없습니다.
cerberos 2016 년

세이브 포인트 방식은 실제 솔루션입니다. PHP, Doctrine2 및 Postgres (9.5) 환경에서도 작동합니다. 감사합니다
helvete

6

이 동작과 관련하여 postgresql JDBC 드라이버에서 일부 작업이 수행되었습니다. https://github.com/pgjdbc/pgjdbc/pull/477을
참조 하십시오.

이제 설정하여 가능합니다

자동 저장 = 항상
'현재 트랜잭션이 중단되었습니다'증후군을 피하기 위해 연결 ( https://jdbc.postgresql.org/documentation/head/connect.html 참조 )에서.
명령문 실행 주위의 세이브 포인트 처리로 인한 오버 헤드는 매우 낮게 유지됩니다 (자세한 내용은 위의 링크 참조).


5

Ruby on Rails PG에서 마이그레이션을 작성하고 DB를 마이그레이션했지만 개발 서버를 다시 시작하는 것을 잊었습니다. 서버를 다시 시작했는데 작동했습니다.


저의 경우이기도합니다. 정말 복잡한 일을 시도하지 않았기 때문에 어리석은 일이라고 생각했습니다.
Tashows

4

이 오류의 원인은 현재 데이터베이스 작업을 수행 할 수없는 잘못된 작업 전에 다른 데이터베이스가 있기 때문입니다 (Google 번역을 사용하여 중국어를 영어로 번역)



2

롤백해야합니다. JDBC Postgres 드라이버는 꽤 나쁩니다. 그러나 트랜잭션을 유지하고 해당 오류를 롤백하려는 경우 저장 점을 사용할 수 있습니다.

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

여기에서 더 읽으십시오 :

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


2

나는 같은 문제가 있었지만 데이터베이스에 같은 이름의 테이블이 있음을 깨달았습니다. 삭제 후 파일을 가져올 수있었습니다.


이것은 내 문제 였고, 나를위한 테이블은 두 가지 다른 스키마에 걸쳐있었습니다.
토마토

0

이것은 PostgreSQL의 매우 이상한 동작이며, 예외가 잡히고 명시 적으로 무시 되었기 때문에 "사용자가 모든 것을 명시 적으로 만들도록 강제하는 PostgreSQL 철학과 맞지 않습니다". 따라서이 방어조차도 유지되지 않습니다. 이 경우 오라클은 훨씬 사용자 친화적이며 올바르게 작동합니다. 개발자에게는 선택의 여지가 있습니다.


0

볼륨의 디스크 공간이 부족한 경우 발생할 수 있습니다.


이것이 가장 일반적인 원인은 아니라는 것을 알고 있지만 서버에서 문제를 해결하라는 요청을 받았습니다. 따라서 이것이 잠재적 인 원인으로 나열되어야한다고 생각합니다.
gregb


0

Postgres와 함께 JDBI를 사용하고 있으며 동일한 문제가 발생했습니다. 즉, 이전 트랜잭션의 명령문에서 일부 제약 조건을 위반 한 후 후속 명령문이 실패합니다 (그러나 잠시 기다렸다가 20-30 초라고 말하면 문제가 사라집니다) ).

약간의 연구 끝에, 문제는 JDBI에서 "수동으로"거래를하고 있다는 것입니다. 즉, 내 진술을 BEGIN; ... COMMIT; 그리고 범인으로 밝혀졌습니다!

JDBI v2에서는 @Transaction 어노테이션을 추가 할 수 있으며 @SqlQuery 또는 @SqlUpdate 내의 명령문은 트랜잭션으로 실행되며 위에서 언급 한 문제는 더 이상 발생하지 않습니다!


0

내 경우에는 파일이 손상 되어이 오류가 발생했습니다. 파일 레코드를 반복하는 동안 동일한 오류가 발생했습니다.

앞으로 누군가에게 도움이 될 것입니다. 이것이이 답변을 게시하는 유일한 이유입니다.


0

@Transactional주석 과 함께 스프링을 사용 하고 예외를 포착하고 일부 예외에 대해 3 번 재 시도합니다.

posgresql의 경우 예외가 발생하면 동일한 Connection을 사용하여 더 이상 커밋 할 수 없습니다. 먼저 롤백해야합니다.

필자의 경우 DatasourceUtils현재 연결을 사용하고 connection.rollback()수동으로 호출 하는 데 사용합니다 . 그리고 다시 시도하기 위해 메소드를 호출합니다.


0

스프링 부트 JPA로 작업하고 @EnableTransactionManagement를 구현하여 수정했습니다.

첨부 파일이 도움이 될 수 있습니다.여기에 이미지 설명을 입력하십시오


0

스프링 부트 JPA로 작업하고 @EnableTransactionManagement를 구현하여 수정했습니다.

첨부 파일이 도움이 될 수 있습니다.


0

이 시도 COMMIT;

pgadmin4에서 실행합니다. 도움이 될 수 있습니다. 이전 명령이 조기에 중지되는 것과 관련이 있습니다.


-1

분리 레벨을 반복 가능한 읽기에서 읽기 커미트로 변경하십시오.


-1

conn.setAutoCommit (false)를 conn.setAutoCommit (true)로 설정하십시오.

새로운 거래를 시작하기 전에 거래를 완결하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.