PSQLException: giao dịch hiện tại bị hủy bỏ, các lệnh bị bỏ qua cho đến khi kết thúc khối giao dịch


151

Tôi đang thấy stacktrace (cắt ngắn) sau trong tệp server.log của 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

Kiểm tra tệp nhật ký Postgres cho thấy các tuyên bố sau:

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

Tôi đang sử dụng Infinispan được gửi cùng với JBoss 7.1.1 Final, là 5.1.2.Final.

Vì vậy, đây là những gì tôi nghĩ đang xảy ra:

  • Infinispan cố gắng chạy SELECT count(*)...câu lệnh để xem có bản ghi nào trong ISPN_MIXED_BINARY_TABLE_configCache;
  • Postgres, vì một số lý do, không thích tuyên bố này.
  • Infinispan bỏ qua điều này và cày trước với CREATE TABLEtuyên bố.
  • Postgres barfs vì nó vẫn nghĩ rằng đó là cùng một giao dịch, mà Infinispan đã thất bại trong việc quay lại và giao dịch này bị hủy bỏ từ SELECT count(*)...tuyên bố đầu tiên .

Lỗi này có ý nghĩa gì và có ý tưởng nào để khắc phục nó không?


Chỉ cần bạn đến đây như tôi đang tìm kiếm ở trên PSQLException: current transaction is aborted...( 25P02) và có thể JPAhoặc Hibernate. Cuối cùng, đó là do việc sử dụng Logback (tốt đẹp!) Của chúng tôi được cung cấp với một toString()đối tượng DAO được tải quá mức gây ra lỗi và bị nuốt một cách độc đáo (nhưng không được tôi chú ý): log.info( "bla bla: {}", obj )được sản xuất bla bla: [FAILED toString()]. thay đổi nó để log.info( "bla bla: {}", String.valueOf( obj )làm cho nó an toàn, nhưng không nuốt nó và do đó khiến giao dịch mở không thành công trên một truy vấn không liên quan.
Andreas Dietrich

Tôi đã nhận được cùng một loại lỗi. Tôi đã phải phát hành kết nối trước khi sql. Mã của tôi là Connection.commit ()
md. ahsan ariful

Câu trả lời:


203

Tôi đã gặp lỗi này khi sử dụng Java và postgresql thực hiện thao tác chèn trên bảng. Tôi sẽ minh họa cách bạn có thể tái tạo lỗi này:

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

Tóm lược:

Lý do bạn gặp phải lỗi này là do bạn đã tham gia một giao dịch và một trong các Truy vấn SQL của bạn không thành công và bạn đã ngấu nghiến thất bại đó và bỏ qua nó. Nhưng thế vẫn chưa đủ, THÌ bạn đã sử dụng cùng một kết nối đó, sử dụng CÙNG GIAO DỊCH để chạy một truy vấn khác. Ngoại lệ được đưa vào truy vấn thứ hai, được hình thành chính xác bởi vì bạn đang sử dụng một giao dịch bị hỏng để thực hiện công việc bổ sung. Postgresql theo mặc định ngăn bạn làm điều này.

Tôi đang sử dụng: 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".

Trình điều khiển postgresql của tôi là: postgresql-9.2-1000.jdbc4.jar

Sử dụng phiên bản java: Java 1.7

Dưới đây là bảng tạo câu lệnh để minh họa Ngoại lệ:

CREATE TABLE moobar
(
    myval   INT
);

Chương trình Java gây ra lỗi:

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

}

Đoạn mã trên tạo ra đầu ra này cho tôi:

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

Cách giải quyết:

Bạn có một vài lựa chọn:

  1. Giải pháp đơn giản nhất: Đừng tham gia giao dịch. Đặt connection.setAutoCommit(false);thành connection.setAutoCommit(true);. Nó hoạt động vì sau đó SQL thất bại chỉ bị bỏ qua như một câu lệnh sql thất bại. Bạn được hoan nghênh thất bại các câu lệnh sql tất cả những gì bạn muốn và postgresql sẽ không ngăn bạn.

  2. Tiếp tục ở trong một giao dịch, nhưng khi bạn phát hiện ra rằng sql đầu tiên đã thất bại, hãy khôi phục / khởi động lại hoặc cam kết / khởi động lại giao dịch. Sau đó, bạn có thể tiếp tục thất bại nhiều truy vấn sql trên kết nối cơ sở dữ liệu đó như bạn muốn.

  3. Đừng bắt và bỏ qua Ngoại lệ được ném khi câu lệnh sql thất bại. Sau đó, chương trình sẽ dừng lại trên truy vấn không đúng định dạng.

  4. Thay vào đó, hãy nhận Oracle, Oracle không đưa ra một ngoại lệ khi bạn không truy vấn được kết nối trong một giao dịch và tiếp tục sử dụng kết nối đó.

Để bảo vệ quyết định của postgresql làm mọi thứ theo cách này ... Oracle đã làm cho bạn trở nên mềm yếu ở giữa cho phép bạn làm những thứ ngớ ngẩn và nhìn ra nó.


10
Lol @ Lựa chọn 4 ... Tôi đã thực hiện khá nhiều sự phát triển trong Oracle và gần đây đã bắt đầu sử dụng Postgres ... thật sự rất khó chịu khi Postgres thực hiện điều này, và bây giờ chúng tôi phải thực sự viết lại một phần lớn chương trình của chúng tôi mà chúng tôi đang chuyển từ Oracle sang Postgres. Tại sao không có tùy chọn như người đầu tiên làm cho nó hoạt động như Oracle nhưng không có cam kết tự động ?
ADTC

2
Phát hiện ra sau một số thử nghiệm rằng Tùy chọn 2 là cách gần nhất mà bạn có thể có đối với hành vi của Oracle. Nếu bạn cần phát hành nhiều bản cập nhật, và một thất bại không nên ngừng cập nhật tiếp theo, chỉ cần gọi rollback()vào Connectionkhi SQLExceptionđang bị bắt. [ Dù sao tôi cũng nhận ra điều này phù hợp với triết lý PostgreSQL buộc người dùng phải làm cho mọi thứ rõ ràng, trong khi Oracle có triết lý ngầm quan tâm đến rất nhiều thứ.]
ADTC

2
Tùy chọn 2 chứa nhánh không thể or commit/restart the transaction. Như tôi có thể thấy không có cách nào để cam kết sau ngoại lệ. Khi tôi cố gắng cam kết - PostgreSQL dorollback
turbanoff

1
Tôi có thể xác nhận vấn đề được nêu ra bởi @turbanoff. Điều này cũng có thể được sao chép trực tiếp với psql. (1) bắt đầu một giao dịch, (2) đưa ra một số tuyên bố hợp lệ, (3) đưa ra một tuyên bố không hợp lệ, (4) cam kết -> psql sẽ phục hồi thay vì cam kết.
Alphaaa

1
postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl một cuộc thảo luận thú vị về chủ đề này. Nếu sự cố này được kích hoạt do vi phạm ràng buộc, nhà phát triển PostgreSQL khuyên bạn nên kiểm tra xung đột trước thời hạn (truy vấn trước khi cập nhật / chèn) hoặc sử dụngsavepoints để quay lại điểm trước khi cập nhật / chèn. Xem stackoverflow.com/a/28640557/14731 để biết mã mẫu.
Gili

27

Kiểm tra đầu ra trước khi tuyên bố gây ra current transaction is aborted. Điều này thường có nghĩa là cơ sở dữ liệu đã ném một ngoại lệ mà mã của bạn đã bỏ qua và hiện đang mong đợi các truy vấn tiếp theo sẽ trả về một số dữ liệu.

Vì vậy, bây giờ bạn có một trạng thái không khớp giữa ứng dụng của bạn, coi mọi thứ đều ổn và cơ sở dữ liệu, yêu cầu bạn phải khôi phục và bắt đầu lại giao dịch của mình ngay từ đầu.

Bạn nên nắm bắt tất cả các trường hợp ngoại lệ và giao dịch rollback trong những trường hợp như vậy.

Đây là một vấn đề tương tự.


Điều đó thật tuyệt, ngoại trừ trong trường hợp này sẽ là Infinispan, thư viện của bên thứ 3, đang nói chuyện với Postgres chứ không phải mã của tôi.
Jimidy

Vâng, tình hình vẫn như vậy - giao dịch phải được khôi phục. Có thể kiểm tra xem có phiên bản mới hơn của thư viện bạn đang sử dụng hoặc phát sinh sự cố trong trình theo dõi lỗi của họ không. Nếu bạn tìm thấy chính xác SQLnguyên nhân gây ra sự cố, bạn sẽ có một số trường để loại bỏ sự cố bằng khả năng mở rộng PostgreQuery.
vyegorov

Có vẻ như bạn đã xác nhận sự nghi ngờ của mình - Tôi sẽ xem xét nguồn Infinispan 5.1.2 ngay bây giờ.
Jimidy

Công bằng mà nói, trong lớp TableManipulation, có một lần thử xung quanh nỗ lực chạy tính chọn (*) .... Có lẽ trình điều khiển Postgres không đưa ra một trong những ngoại lệ dự kiến. Tôi sẽ kết nối một trình sửa lỗi với JBoss để cố gắng tìm hiểu thêm.
Jimidy

Mã Infinispan trong câu hỏi đã được đề xuất trong lỗi này: problems.jboss.org/browse/, Tôi đã đính kèm một trình gỡ lỗi cho nó chạy trên một phiên bản JBoss 7.1.1 trực tiếp và Postgres đang ném ngoại lệ vào đúng chỗ. Có lẽ đó là các câu lệnh JdbcUtil.safeClose () không hoạt động. Tôi sẽ nâng nó với Infinispan.
Jimidy

13

Tôi nghĩ rằng giải pháp tốt nhất là sử dụng java.sql.Savepoint.

Trước khi thực hiện truy vấn có thể ném phương thức SQLException, hãy sử dụng phương thức Connection.setSavepoint () và nếu ngoại lệ sẽ bị ném, bạn chỉ quay ngược lại điểm lưu trữ này chứ không quay ngược lại tất cả giao dịch.

Mã ví dụ:

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

   }
}

Tôi vô tình hạ cấp bằng cách nào đó, chỉ nhận thấy. Không cố ý, tôi không thể hoàn tác trừ khi câu trả lời được chỉnh sửa.
cerberos

Cách lưu điểm là giải pháp thực tế. Hoạt động với tôi cũng trong môi trường của PHP, Doctrine2 và Postgres (9.5). Cảm ơn
trực thăng

6

Đã có một số công việc được thực hiện trên Trình điều khiển JDBC postgresql, liên quan đến hành vi này:
xem https://github.com/pgjdbc/pgjdbc/pull/477

Bây giờ có thể, bằng cách thiết lập

tự động lưu = luôn
trong kết nối (xem https://jdbc.postgresql.org/documentation/head/connect.html ) để tránh hội chứng 'giao dịch hiện tại bị hủy bỏ'.
Chi phí hoạt động do xử lý một điểm lưu trữ xung quanh việc thực thi câu lệnh được giữ ở mức rất thấp (xem liên kết ở trên để biết chi tiết).


5

Trong Ruby on Rails PG, tôi đã tạo một di chuyển, di chuyển DB của mình, nhưng quên khởi động lại máy chủ phát triển của mình. Tôi khởi động lại máy chủ của tôi và nó hoạt động.


Đó là trường hợp của tôi là tốt. Nghĩ rằng nó sẽ là một cái gì đó ngu ngốc, bởi vì tôi đã không thực sự cố gắng làm bất cứ điều gì phức tạp.
Tashows

4

Lý do cho lỗi này là có các cơ sở dữ liệu khác trước khi thao tác sai dẫn đến hoạt động cơ sở dữ liệu hiện tại không thể được thực hiện tôi sử dụng google dịch để dịch tiếng Trung Quốc sang tiếng Anh



2

Bạn cần phải quay lại. Trình điều khiển JDBC Postgres khá tệ. Nhưng nếu bạn muốn giữ giao dịch của mình và chỉ cần khắc phục lỗi đó, bạn có thể sử dụng các điểm lưu trữ:

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

Đọc thêm tại đây:

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


2

Tôi đã có cùng một vấn đề nhưng sau đó nhận ra có một bảng có cùng tên trong cơ sở dữ liệu. Sau khi xóa rằng tôi đã có thể nhập tệp.


Đây là vấn đề của tôi, các bảng cho tôi nằm trên hai lược đồ khác nhau.
cà chua

0

Đây là hành vi rất kỳ lạ của PostgreSQL, nó thậm chí không "phù hợp với triết lý PostgreQuery khi buộc người dùng phải làm mọi thứ rõ ràng" - vì ngoại lệ đã bị bắt và bỏ qua một cách rõ ràng. Vì vậy, ngay cả phòng thủ này không giữ. Oracle trong trường hợp này hành xử thân thiện với người dùng hơn nhiều và (đối với tôi) chính xác - nó để lại sự lựa chọn cho nhà phát triển.


0

Điều này có thể xảy ra nếu bạn hết dung lượng đĩa trên ổ đĩa.


Tôi nhận ra đây không phải là nguyên nhân phổ biến nhất, nhưng đây là trường hợp trên máy chủ mà tôi được yêu cầu khắc phục sự cố. Vì vậy, tôi nghĩ rằng điều này nên được liệt kê như là một nguyên nhân tiềm năng.
gregb


0

Tôi đang sử dụng JDBI với Postgres và gặp phải cùng một vấn đề, tức là sau khi vi phạm một số ràng buộc từ một tuyên bố của giao dịch trước đó, các báo cáo tiếp theo sẽ thất bại (nhưng sau khi tôi chờ một lúc, giả sử 20-30 giây, vấn đề sẽ biến mất ).

Sau một số nghiên cứu, tôi thấy vấn đề là tôi đang thực hiện giao dịch "thủ công" trong JDBI của mình, tức là tôi đã bao quanh các tuyên bố của mình bằng BEGIN; ... CAM KẾT; và hóa ra là thủ phạm!

Trong JDBI v2, tôi chỉ có thể thêm chú thích @Transaction và các câu lệnh trong @SqlQuery hoặc @SqlUpdate sẽ được thực thi như một giao dịch và vấn đề được đề cập ở trên không còn xảy ra nữa!


0

Trong trường hợp của tôi, tôi đã nhận được lỗi này vì tập tin của tôi bị hỏng. Trong khi lặp lại các bản ghi của các tập tin, nó đã cho tôi cùng một lỗi.

Có thể trong tương lai nó sẽ giúp cho bất cứ ai. Đó là lý do duy nhất để đăng câu trả lời này.


0

Tôi sử dụng mùa xuân với @Transactionalchú thích, và tôi bắt được ngoại lệ và đối với một số ngoại lệ, tôi sẽ thử lại 3 lần.

Đối với posgresql, khi có ngoại lệ, bạn không thể sử dụng cùng một Kết nối để cam kết nữa. Trước tiên, bạn phải quay lại.

Đối với trường hợp của tôi, tôi sử dụng DatasourceUtilsđể có được kết nối hiện tại và gọi connection.rollback()thủ công. Và cuộc gọi phương thức tuyển dụng để thử lại.


0

Tôi đã làm việc với spring boot jpa và đã sửa bằng cách triển khai @EnableTransactionMan Management

Tập tin đính kèm có thể giúp bạn.nhập mô tả hình ảnh ở đây


0

Tôi đã làm việc với spring boot jpa và đã sửa bằng cách triển khai @EnableTransactionMan Management

Tập tin đính kèm có thể giúp bạn.


0

Thử cái này COMMIT;

Tôi chạy nó trong pgadmin4. Nó có thể giúp. Nó phải làm với lệnh trước dừng sớm


-1

Thay đổi mức cô lập từ đọc lặp lại thành đọc cam kết.


-1

Đặt Conn.setAutoCommit (false) thành Conn.setAutoCommit (true)

Cam kết các giao dịch trước khi bắt đầu một giao dịch mới.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.