ORA-1000-Fehler in Oracle-Datenbanksitzung geöffnet Dieser Fehler tritt auf, wenn die Anzahl der Cursor den Maximalwert überschreitet.
ORA-1000 Die maximale Anzahl offener Cursor wurde überschritten.
Versuchen wir es sofort. 彡 (゜) (゜) Bereiten Sie zuerst den Tisch vor.
CREATE TABLE TBL_A(
C1 NUMBER
, C2 VARCHAR2(30)
);
In SQL, einer Bindungsvariablen von PreparedStatement, Die Quelle ist so geschrieben, dass Tricks und ORA-1000-Fehler auftreten.
In der for-Schleife befindet sich eine prepareStatement-Methode, und der Cursor wird jedes Mal bewegt. Es wird neu geöffnet und es tritt ein Fehler auf. 彡 (゚) (゚)
Es ist voller verdammter Codeelemente, aber wenn ich Masakari überspringe (Akan 彡 (-) (-)
import java.sql.*;
import java.util.Date;
public class InsertTest {
public static void main(String[] args) throws Exception {
//DB connection info
final String path = "jdbc:oracle:thin:@127.0.0.1:1521/orcl"; //path
final String id = "xxxxxxxx"; //ID
final String pw = "yyyyyyyy"; //password
int i;
Connection conn = null;
PreparedStatement ps = null;
System.out.println(new Date() + " Connect...");
try {
//DB Connect
conn = DriverManager.getConnection(path, id, pw);
//AutoCommit Setting
conn.setAutoCommit(false);
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
//Prepared Statement Set.
ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
//Close
conn.close();
} catch(SQLException ex) {
conn.rollback();
ex.printStackTrace();
System.exit(1);
} finally {
if (ps != null) { ps.close(); }
if (conn != null) { conn.close(); }
}
//End
System.out.println(new Date() + " End...");
}
}
Bei der Ausführung tritt der folgende ORA-1000-Fehler auf: 彡 (゚) (゚)
$ javac ./InsertTest.java
$ java -classpath .:${ORACLE_HOME}/jdbc/lib/ojdbc8.jar InsertTest
Thu Nov 30 00:57:01 JST 2017 Connect...
Thu Nov 30 00:57:23 JST 2017 Insert...
java.sql.SQLException: ORA-01000: maximum open cursors exceeded
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:494)
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:446)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1054)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:623)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:612)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:226)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:59)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:910)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1119)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3780)
at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1343)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3887)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1079)
at InsertTest.main(InsertTest.java:27)
Caused by: Error : 1000, Position : 0, Sql = INSERT INTO TBL_A (C1, C2) VALUES (:1 , :2 ), OriginalSql = INSERT INTO TBL_A (C1, C2) VALUES (?, ?), Error Msg = ORA-01000: maximum open cursors exceeded
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:498)
... 14 more
$ echo $?
1
Wenn Sie das prepareStatement außerhalb der for-Schleife platzieren, Sie können den ORA-1000-Fehler vermeiden. Ist das so? 彡 (゜) (゜)
:
//Insert Execute
System.out.println(new Date() + " Insert...");
//Prepared Statement Set.
ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
for (i = 1; i <= 2000; i++) {
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
:
Nullprüfung des Objekts und des ersten prepareStatements Wenn Sie dies tun, können Sie den ORA-1000-Fehler vermeiden.
:
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
//Prepared Statement Set.
if (ps == null) {
ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
}
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
:
Es wird eine Variation der Problemumgehung 1 sein. 彡 (゚) (゚) Wenn Sie die im vorherigen Artikel beschriebene Try-with-Resources-Syntax verwenden, Vermeiden Sie das erste Anti-Pattern-Schreiben "natürlich" ORA-1000-Fehler tritt nicht auf. Der Punkt ist "natürlich".
Die Quelle ist sauber und alle guten Dinge sind 彡 (゚) (゚)
import java.sql.*;
import java.util.Date;
public class InsertTest {
public static void main(String[] args) {
//DB connection info
final String path = "jdbc:oracle:thin:@127.0.0.1:1521/orcl"; //path
final String id = "xxxxxxxx"; //ID
final String pw = "yyyyyyyy"; //password
//try-with-resources Statement
System.out.println(new Date() + " Connect...");
try (
//DB Connect
Connection conn = DriverManager.getConnection(path, id, pw);
//Prepared Statement Set.
PreparedStatement ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
) {
//Initialize
int i;
//AutoCommit Setting
conn.setAutoCommit(false);
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
} catch(SQLException ex) {
ex.printStackTrace();
System.exit(1);
}
//End
System.out.println(new Date() + " End...");
}
}
PreparedStatement-Objekt in einer Schleife Sie können den ORA-1000-Fehler vermeiden, indem Sie jedes Mal () schließen.
:
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
//Prepared Statement Set.
ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
ps.close();
}
//Commit
conn.commit();
:
Ist es schwierig, jedes Mal zu analysieren, wenn ich so schreibe? Ich dachte, Hard Parse kann jedes Mal mit der Anweisungs-Cache-Funktion 彡 (゚) (゚) vermieden werden.
Informationen zum Anweisungscache https://docs.oracle.com/cd/E16338_01/java.112/b56281/stmtcach.htm#i1069942 : -Vermeidet wiederholte Analyse und Bildung von Sätzen. :
Eine andere Person fragte: "Ist der Umfang der Variablen im Anti-Pattern nicht überhaupt seltsam?" Ich wurde darauf hingewiesen, also wenn ich die Quelle ändere, um die Variable in der try-Klausel zu deklarieren ... Nun, es wird natürlich ein Workaround 1.-ähnlicher Code. Die Try-with-Resources-Syntax ist wichtig, nicht wahr? (゜) (゜)
import java.sql.*;
import java.util.Date;
public class InsertTest {
public static void main(String[] args) {
//DB connection info
final String path = "jdbc:oracle:thin:@127.0.0.1:1521/orcl"; //path
final String id = "xxxxxxxx"; //ID
final String pw = "yyyyyyyy"; //password
System.out.println(new Date() + " Connect...");
try {
//Init
int i;
//DB Connect
Connection conn = DriverManager.getConnection(path, id, pw);
//AutoCommit Setting
conn.setAutoCommit(false);
//Prepared Statement Set.
PreparedStatement ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.execute();
}
//Commit
conn.commit();
//Close
ps.close();
conn.close();
} catch(SQLException ex) {
ex.printStackTrace();
System.exit(1);
}
//End
System.out.println(new Date() + " End...");
}
}
Ich habe in den Kommentaren einen Kommentar zu addBatch erhalten, daher habe ich ihn basierend auf der zusätzlichen Quelle geändert. Ich frage mich, ob es so in Ordnung ist ... 彡 (゚) (゚) Das Handbuch für addBatch (Batch-Update) ist [hier](https://docs.oracle.com/cd/F19136_01/jjdbc/performance-extensions.html#GUID -FEECA64F-44F4-453F-B8A8-AFBF6D29ABA4)
import java.sql.*;
import java.util.Date;
public class InsertTest {
public static void main(String[] args) {
//DB connection info
final String path = "jdbc:oracle:thin:@127.0.0.1:1521/orcl"; //path
final String id = "xxxxxxxx"; //ID
final String pw = "yyyyyyyy"; //password
System.out.println(new Date() + " Connect...");
try {
//Init
int i;
//DB Connect
Connection conn = DriverManager.getConnection(path, id, pw);
//AutoCommit Setting
conn.setAutoCommit(false);
//Prepared Statement Set.
PreparedStatement ps = conn.prepareStatement("INSERT INTO TBL_A (C1, C2) VALUES (?, ?)");
//Insert Execute
System.out.println(new Date() + " Insert...");
for (i = 1; i <= 2000; i++) {
ps.setInt(1, i);
ps.setString(2, "A" + String.valueOf(i));
ps.addBatch();
}
//Execute(batch updates)
int[] updateCounts = ps.executeBatch();
System.out.println(new Date() + " Batch Counts..." + updateCounts.length);
//Commit
conn.commit();
//Close
ps.close();
conn.close();
} catch(SQLException ex) {
ex.printStackTrace();
System.exit(1);
}
//End
System.out.println(new Date() + " End...");
}
}
$ javac ./InsertTest.java
$ java -classpath .:/u01/app/oracle/product/version/db_1/jdbc/lib/ojdbc8.jar InsertTest
Tue Aug 20 04:18:11 EDT 2019 Connect...
Tue Aug 20 04:18:13 EDT 2019 Insert...
Tue Aug 20 04:18:14 EDT 2019 Batch Counts...2000
Tue Aug 20 04:18:14 EDT 2019 End...
$
Recommended Posts