PSQLException: การทำธุรกรรมปัจจุบันถูกยกเลิกคำสั่งถูกละเว้นจนกว่าจะสิ้นสุดการบล็อกธุรกรรม


152

ฉันเห็น stacktrace (ตัด) ต่อไปนี้ในไฟล์ 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

การตรวจสอบไฟล์บันทึก 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

ฉันใช้ Infinispan มาพร้อมกับ JBoss 7.1.1 Final ซึ่งเป็น 5.1.2 สุดท้าย

ดังนั้นนี่คือสิ่งที่ฉันคิดว่าจะเกิดขึ้น:

  • Infinispan พยายามเรียกใช้SELECT count(*)...คำสั่งเพื่อดูว่ามีบันทึกใด ๆ ในISPN_MIXED_BINARY_TABLE_configCache;
  • Postgres ด้วยเหตุผลบางอย่างไม่ชอบคำสั่งนี้
  • Infinispan เพิกเฉยต่อสิ่งนี้และพุ่งไปข้างหน้าพร้อมกับCREATE TABLEแถลงการณ์
  • postgres barfs เพราะมันยังคิดว่าเป็นธุรกรรมเดียวกันซึ่ง Infinispan ไม่สามารถย้อนกลับและธุรกรรมนี้ถูก shafted จากSELECT count(*)...คำสั่งแรก

ข้อผิดพลาดนี้หมายถึงอะไรและมีแนวคิดใดที่จะแก้ไขได้


เพียงถ้าคุณมาที่นี่เหมือนผมค้นหาข้างต้นPSQLException: current transaction is aborted...( 25P02) และอาจจะยังหรือJPA Hibernateในที่สุดมันก็เป็นเพราะเรา (ดี!) Logbackการใช้งานเลี้ยงกับtoString()วัตถุ DAO -overloaded ที่ก่อให้เกิดข้อผิดพลาดและถูกกลืนกินอย่าง ( แต่ไม่มีใครสังเกตเห็น accidentially โดยฉัน): การผลิตlog.info( "bla bla: {}", obj ) bla bla: [FAILED toString()]เปลี่ยนเป็นlog.info( "bla bla: {}", String.valueOf( obj )ทำให้ปลอดภัย แต่ไม่กลืนและทำให้ธุรกรรมเปิดไม่สำเร็จในการสอบถามที่ไม่เกี่ยวข้อง
Andreas Dietrich

ฉันได้รับข้อผิดพลาดประเภทเดียวกัน ฉันต้องปล่อยการเชื่อมต่อก่อน sql รหัสของฉันคือ connection.commit ()
md ahsan ariful

คำตอบ:


203

ฉันพบข้อผิดพลาดนี้โดยใช้ Java และ postgresql ทำการแทรกบนตาราง ฉันจะแสดงให้เห็นว่าคุณสามารถทำซ้ำข้อผิดพลาดนี้ได้อย่างไร:

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

สรุป:

สาเหตุที่คุณได้รับข้อผิดพลาดนี้คือเนื่องจากคุณป้อนธุรกรรมและหนึ่งในแบบสอบถาม SQL ของคุณล้มเหลวและคุณ gobbled อัพความล้มเหลวนั้นและละเว้นมัน แต่นั่นยังไม่เพียงพอจากนั้นคุณใช้การเชื่อมต่อเดียวกันโดยใช้การทำธุรกรรมเดียวกันเพื่อเรียกใช้แบบสอบถามอื่น ข้อยกเว้นจะถูกส่งออกไปในคิวรีที่สองที่สร้างขึ้นอย่างถูกต้องเนื่องจากคุณใช้ธุรกรรมที่เสียหาย 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: 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 แทน Oracle จะไม่ส่งข้อยกเว้นเมื่อคุณไม่ได้สอบถามเกี่ยวกับการเชื่อมต่อภายในธุรกรรมและใช้การเชื่อมต่อนั้นต่อไป

ในการป้องกันของการตัดสินใจของ PostgreSQL ที่จะทำสิ่งต่างๆด้วยวิธีนี้ ... ออราเคิลได้รับการทำให้คุณนุ่มในกลางปล่อยให้คุณทำสิ่งที่เป็นใบ้และสามารถมองเห็นมัน


10
Lol @ ตัวเลือก 4 ... ฉันได้ทำการพัฒนาเล็กน้อยใน Oracle และเพิ่งเริ่มใช้ Postgres ... มันน่ารำคาญจริง ๆ ที่ Postgres ทำเช่นนี้และตอนนี้เราต้องเขียนโปรแกรมจำนวนมากของเราใหม่ กำลังพอร์ตจาก Oracle ไปยัง Postgres ทำไมไม่มีตัวเลือกอย่างแรกที่ทำให้มันทำงานเหมือนกับ Oracle แต่ไม่มีการยืนยันอัตโนมัติ ?
ADTC

2
ค้นพบหลังจากการทดลองบางอย่างที่ตัวเลือก 2ใกล้เคียงที่สุดที่คุณสามารถเข้าถึงพฤติกรรมของออราเคิล หากคุณต้องการที่จะแก้ไขปัญหาการปรับปรุงหลายและเป็นหนึ่งในความล้มเหลวไม่ควรหยุดการปรับปรุงที่ตามมาเพียงโทรrollback()ในConnectionเมื่อSQLExceptionถูกจับได้ [ อย่างไรก็ตามผมตระหนักในเรื่องนี้อยู่ในแนวเดียวกันกับปรัชญา PostgreSQL การบังคับให้ผู้ใช้เพื่อให้ทุกอย่างชัดเจนในขณะที่ Oracle มีปรัชญาของโดยปริยายการดูแลจำนวนมากของสิ่งที่.]
ADTC

2
ตัวเลือกที่ 2or commit/restart the transactionมีสาขาที่เป็นไปไม่ได้ อย่างที่ฉันเห็นไม่มีหนทางใดที่จะยอมรับหลังจากข้อยกเว้น เมื่อฉันพยายามคอมมิชชัน - PostgreSQL ทำrollback
turbanoff

1
ฉันสามารถยืนยันปัญหาที่เกิดจาก @turbanoff psqlนอกจากนี้ยังสามารถทำซ้ำโดยตรงกับ (1) เริ่มทำธุรกรรม (2) ออกข้อความที่ถูกต้องบางส่วน (3) ออกข้อความที่ไม่ถูกต้อง (4) ส่ง -> psql จะย้อนกลับแทนที่จะทำ
Alphaaa

1
postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl การอภิปรายที่น่าสนใจของหัวข้อนี้ หากปัญหานี้เกิดขึ้นจากการละเมิดข้อ จำกัด PostgreSQL devs แนะนำให้ตรวจสอบความขัดแย้งล่วงหน้า (แบบสอบถามก่อนอัปเดต / แทรก) หรือใช้savepointsเพื่อย้อนกลับไปยังจุดก่อนการอัปเดต / แทรก ดูstackoverflow.com/a/28640557/14731สำหรับโค้ดตัวอย่าง
Gili

27

ตรวจสอบผลลัพธ์ก่อนคำสั่งที่เกิดcurrent transaction is abortedขึ้น โดยทั่วไปแล้วหมายความว่าฐานข้อมูลมีข้อยกเว้นที่รหัสของคุณเพิกเฉยและตอนนี้คาดว่าคำสั่งถัดไปจะส่งคืนข้อมูล

ดังนั้นขณะนี้คุณมีสถานะไม่ตรงกันระหว่างแอปพลิเคชันของคุณซึ่งถือว่าเป็นสิ่งที่ดีและฐานข้อมูลที่คุณต้องย้อนกลับและเริ่มต้นธุรกรรมของคุณใหม่ตั้งแต่ต้น

คุณควรตรวจสอบข้อยกเว้นและธุรกรรมย้อนกลับในกรณีดังกล่าว

นี่คือปัญหาที่คล้ายกัน


เยี่ยมมากยกเว้นในกรณีนี้จะเป็น Infinispan ห้องสมุดบุคคลที่สามกำลังพูดคุยกับ Postgres ไม่ใช่รหัสของฉัน
Jimidy

สถานการณ์ยังคงเหมือนเดิม - ต้องย้อนทรานแซกชัน อาจตรวจสอบว่ามีไลบรารี่รุ่นใหม่ที่คุณใช้อยู่หรือมีปัญหาเพิ่มขึ้นในเครื่องมือติดตามบั๊ก หากคุณพบสิ่งSQLที่ทำให้เกิดปัญหาคุณจะมีบางฟิลด์ที่จะกำจัดปัญหาโดยใช้การเพิ่มความสามารถของ PostgreSQL
vyegorov

ดูเหมือนว่าคุณได้ยืนยันข้อสงสัยแล้ว - ฉันจะดูที่แหล่ง Infinispan 5.1.2 ทันที
Jimidy

เพื่อความเป็นธรรมในคลาส TableManipulation มีความพยายามรอบด้านเพื่อพยายามเลือก count (*) .... บางทีไดรเวอร์ Postgres อาจไม่ได้โยนข้อยกเว้นที่คาดไว้ ฉันจะขอดีบักเกอร์ไปที่ JBoss เพื่อหาข้อมูลเพิ่มเติม
Jimidy

ขอแนะนำให้ใช้รหัส Infinispan ในข้อผิดพลาดนี้: problems.jboss.org/browse/ … ฉันได้แนบตัวดีบักเกอร์เพื่อใช้งานอินสแตนซ์ JBoss 7.1.1 แบบสดและ Postgres กำลังโยนข้อยกเว้นในสถานที่ที่เหมาะสม อาจเป็นคำสั่ง JdbcUtil.safeClose () ที่ไม่ได้ทำงาน ฉันจะเลี้ยงมันด้วย Infinispan
Jimidy

13

ฉันคิดว่าทางออกที่ดีที่สุดคือใช้ java.sql.Savepoint

ก่อนที่จะดำเนินการสืบค้นซึ่งสามารถโยน SQLException ใช้วิธีการเชื่อมต่อ. setSavepoint () และถ้าข้อยกเว้นจะถูกโยนคุณเพียงย้อนกลับไปที่ savepoint นี้ไม่ย้อนกลับการทำธุรกรรมทั้งหมด

รหัสตัวอย่าง:

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

วิธี savepoint เป็นทางออกที่แท้จริง ทำงานได้ดีสำหรับฉันในสภาพแวดล้อมของ PHP, Doctrine2 และ Postgres (9.5) ขอบคุณ
helvete

6

มีการทำงานบางอย่างกับไดรเวอร์ JDBC postgresql ที่เกี่ยวข้องกับพฤติกรรมนี้:
ดูhttps://github.com/pgjdbc/pgjdbc/pull/477

ตอนนี้มันเป็นไปได้โดยการตั้งค่า

บันทึกอัตโนมัติ = เสมอ
ในการเชื่อมต่อ (ดูที่https://jdbc.postgresql.org/documentation/head/connect.html ) เพื่อหลีกเลี่ยงการ 'ยกเลิกการทำธุรกรรมปัจจุบัน'
ค่าโสหุ้ยเนื่องจากการจัดการ savepoint รอบการดำเนินการคำสั่งจะถูกเก็บไว้ต่ำมาก (ดูลิงค์ด้านบนเพื่อดูรายละเอียด)


5

ใน Ruby on Rails PG ฉันได้สร้างการโยกย้ายโยกย้ายฐานข้อมูลของฉัน แต่ลืมรีสตาร์ทเซิร์ฟเวอร์การพัฒนาของฉัน ฉันรีสตาร์ทเซิร์ฟเวอร์และใช้งานได้


นั่นเป็นกรณีของฉันเช่นกัน คิดว่ามันควรจะเป็นสิ่งที่โง่เพราะฉันไม่ได้พยายามทำสิ่งที่ซับซ้อน
Tashows

4

สาเหตุของข้อผิดพลาดนี้คือมีฐานข้อมูลอื่นก่อนที่การดำเนินการที่ผิดจะนำไปสู่การดำเนินการฐานข้อมูลปัจจุบันไม่สามารถทำได้ (ฉันใช้การแปล google เพื่อแปลภาษาจีนเป็นภาษาอังกฤษ)



2

คุณต้องย้อนกลับ ไดรเวอร์ JDBC Postgres ค่อนข้างแย่ แต่ถ้าคุณต้องการที่จะรักษาธุรกรรมของคุณและเพียงแค่ย้อนกลับข้อผิดพลาดนั้นคุณสามารถใช้ savepoints:

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 ที่บังคับให้ผู้ใช้ต้องทำให้ทุกอย่างชัดเจน" - เนื่องจากข้อยกเว้นถูกตรวจจับและละเว้นอย่างชัดเจน ดังนั้นแม้การป้องกันนี้จะไม่ถือ Oracle ในกรณีนี้มีพฤติกรรมที่ใช้งานง่ายและถูกต้อง (สำหรับฉัน) - เป็นตัวเลือกสำหรับนักพัฒนา


0

สิ่งนี้สามารถเกิดขึ้นได้หากคุณมีพื้นที่ดิสก์ไม่เพียงพอในโวลุ่ม


ฉันรู้ว่านี่ไม่ใช่สาเหตุที่พบบ่อยที่สุด แต่นี่เป็นกรณีบนเซิร์ฟเวอร์ที่ฉันถูกขอให้แก้ไขปัญหา ดังนั้นฉันคิดว่าสิ่งนี้ควรถูกระบุว่าเป็นสาเหตุที่เป็นไปได้
gregb


0

ฉันกำลังใช้ JDBI กับ Postgres และพบปัญหาเดียวกันคือหลังจากการละเมิดข้อ จำกัด บางอย่างจากคำสั่งของการทำธุรกรรมก่อนหน้าคำสั่งที่ตามมาจะล้มเหลว (แต่หลังจากฉันรอครู่หนึ่งพูด 20-30 วินาทีปัญหาหายไป )

หลังจากการวิจัยบางอย่างฉันพบว่าปัญหาคือฉันกำลังทำธุรกรรม "ด้วยตนเอง" ใน JDBI ของฉันคือฉันล้อมรอบงบของฉันกับ BEGIN; ... COMMIT; และกลายเป็นผู้ร้าย!

ใน JDBI v2 ฉันสามารถเพิ่มคำอธิบายประกอบ @Transaction และคำสั่งภายใน @SqlQuery หรือ @SqlUpdate จะถูกดำเนินการเป็นธุรกรรมและปัญหาดังกล่าวข้างต้นไม่ได้เกิดขึ้นอีกแล้ว!


0

ในกรณีของฉันฉันได้รับข้อผิดพลาดนี้เพราะไฟล์ของฉันเสียหาย ในขณะที่วนซ้ำระเบียนของไฟล์มันทำให้ฉันมีข้อผิดพลาดเดียวกัน

อาจจะเป็นในอนาคตมันจะช่วยให้ทุกคน นั่นเป็นเหตุผลเดียวที่โพสต์คำตอบนี้


0

ฉันใช้สปริงพร้อม@Transactionalคำอธิบายประกอบและฉันจับข้อยกเว้นและสำหรับข้อยกเว้นบางอย่างฉันจะลองอีก 3 ครั้ง

สำหรับ posgresql เมื่อได้รับข้อยกเว้นคุณไม่สามารถใช้การเชื่อมต่อเดียวกันเพื่อกระทำการใด ๆ เพิ่มเติมคุณต้องย้อนกลับก่อน

สำหรับกรณีของฉันฉันใช้DatasourceUtilsเพื่อรับการเชื่อมต่อปัจจุบันและโทรconnection.rollback()ด้วยตนเอง และการเรียกใช้วิธีการ recruive เพื่อลองอีกครั้ง




0

ลองสิ่งนี้ COMMIT;

ฉันเรียกใช้ใน pgadmin4 อาจช่วยได้ มันจะทำอย่างไรกับคำสั่งก่อนหน้านี้หยุดก่อนเวลาอันควร


-1

เปลี่ยนระดับการแยกจากการอ่านซ้ำเพื่ออ่านความมุ่งมั่น


-1

ตั้งค่า conn.setAutoCommit (false) เป็น conn.setAutoCommit (จริง)

ทำธุรกรรมก่อนที่จะเริ่มใหม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.