The Following Exception is really Frequency When we Using Oracle.
1. ORA-02292: integrity constraint (IPCUSER.STUDENT_STUDENTCARD_FK) violated - child record found
If you delete a row from a table, and one of this row's columns referenced by another table, and then this Exception been throwed.
the stacktrace info:
java.sql.SQLException: ORA-02292: integrity constraint (IPCUSER.STUDENT_STUDENTCARD_FK) violated - child record found at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745) at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210) at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:961) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190) at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1726) at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1696) at com.tibco.ipc.utils.TESTClient.main(TESTClient.java:48)
2. ORA-02291: integrity constraint (IPCUSER.STUDENT_STUDENTCARD_FK) violated - parent key not found
If you insert a row to a table(table_a), and this row has a foreign key refered to another table(table_b), and the foreign key's value can not be found from another table(table_b), then this Exception been thowed.
the stacktrace info:
java.sql.SQLException: ORA-02291: integrity constraint (IPCUSER.STUDENT_STUDENTCARD_FK) violated - parent key not found at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745) at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210) at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:961) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190) at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1726) at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1696) at com.tibco.ipc.utils.TESTClient.main(TESTClient.java:48)
3. ORA-00001: unique constraint (IPCUSER.STUDENTCARD_HID_PK) violated
If you insert a row to a table, one of this row's column is primary key, and if the primary key you want to insert already existed in table, this Exception been throwed.
The StackTrace info:
java.sql.SQLException: ORA-00001: unique constraint (IPCUSER.STUDENTCARD_HID_PK) violated at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745) at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210) at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:961) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190) at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1726) at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1696) at com.tibco.ipc.utils.TESTClient.main(TESTClient.java:46)
4.ORA-01591: lock held by in-doubt distributed transaction 8.12.9742
The stacktrace information:
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745) at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219) at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:970) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370) at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3454)
Refering to this Exception, We should learn this fllowing issues firstly, before we discussing this point:
1> Understanding 'Oracle two-phase commit mechanism':
Two-phase commit is a mechanism that guarantees a distributed transaction either commits on all involved nodes or rollback on all involved nodes to maintain data consistency across the global distributed database. It has two phase, a Prepare Phase and a Commit Phase. The Objective of the two-phase commit mechanism is that that all nodes either commit or perform a rollback together, to maintain the data's integrity and consistency.
2> Oracle distribution Transaction
To make this issue more explicity and clearly we providing the following experiments:
As figure depicted, 2 JDBC Connection in different JVM connected to the same databse, and update the same table's same row. Assuming the table name is 'HOMETEST', the row is 'Row 1', 'HOMETEST' is very simple, the create SQL statements:
CREATE TABLE HOMETEST( HID NUMBER(19,0) CONSTRAINT HOMETEST_HID_NN NOT NULL, NAME VARCHAR2(255), CONSTRAINT HOMETEST_HID_PK PRIMARY KEY(HID) )
Two JVM update table's procedure is very samilary, like the following figure depicted:
continuely assuming: JVM I and JVM II update row 1 cosistantly and simultaneously, JVM I,eachtime change row 1's column 'NAME''s value add 1 and without stopping; Oppositely; JVM II, eachtime reset row 1's column 'NAME''s value, and exist without commit in the 10th time. reserence Java Code:
JVM I:
int i = 1; Connection conn = getConnection(); Statement s = null; while(true) { String upSql = "UPDATE HOMETEST SET HOMETEST.NAME = 'kylinsoong-" + i + "' WHERE HOMETEST.HID = 1"; try { conn.setAutoCommit(false); s = conn.createStatement(); s.executeUpdate(upSql); int sleep = new Random().nextInt(100); System.out.println("Update Thread Sleep " + sleep + " milliseconds"); Thread.sleep(sleep); i ++ ; conn.commit(); } catch (Exception e) { e.printStackTrace(); } finally { close(null, s, null); }
JVM II Sides:
int index = 1; while(true) { try { conn.setAutoCommit(false); s = conn.createStatement(); s.executeUpdate(rmSql); s.executeUpdate(adSql); int sleep = new Random().nextInt(100); System.out.println("Insert Thread Sleep " + sleep + " milliseconds -> " + index); Thread.sleep(sleep); if(index ++ == 10) { Thread.sleep(60000); break; } conn.commit(); } catch (Exception e) { e.printStackTrace(); } finally { close(null, s, null); } }
The Experment Results:
When JVM II executed the 10th times update, sleeping 1 minute, the JVM I also in stucked state;
The finally value in row 1 Name column is always kylinsoong-10, even after JVM I stopped. That's because JVM I and JVM II update row 1 are totally involved, JVM II could not update row 1 if JVM I transacted row 1.
The Conclusion: The Oracle distribution Transaction is not real distributed, All involved Node always in a order list, execute order list base on FIFO, in other words, Oracle distribution Transaction just like run multiple-thread application in single process mechine.
3>