达梦数据库语句句柄个数超上限或系统内存不足

句柄与对象创建的个数有关
在数据库插入过程中出现如下报错:
达梦数据库语句句柄个数超上限或系统内存不足_第1张图片

此时jdbc的日志为
达梦数据库语句句柄个数超上限或系统内存不足_第2张图片

其中句柄数pstmt-200 达到200个,连接数conn-1只有一个
此时相关参数为:
MAX_SESSIONS = 100#最大会话数
MAX_SESSION_STATEMENT = 200#一个会话最大的句柄数
可以通过调大MAX_SESSION_STATEMENT参数暂时解决问题,但无法从根本上解决问题。
可以使用查看连接会话的句柄使用情况

select sql_text,state,n_stmt  "句柄的容量",n_used_stmt as "使用的句柄数",curr_sch,user_name,trx_id,create_time,clnt_type,clnt_ip,run_status from v$sessions;

程序插入代码为
达梦数据库语句句柄个数超上限或系统内存不足_第3张图片

在代码可以看到在for循环中除参数的传递之外还有一个
prest = con.prepareStatement(sql1);
寻其源码:
达梦数据库语句句柄个数超上限或系统内存不足_第4张图片

有这样的解释,通过传入含有占位符的sql语句返回PreparedStatement对象,通过对PreparedStatement的操作进而转化为为对数据库的操作,在这个对象类中的方法我们可以看到如此多的方法,这些方法提供了占位符转化为指定参数的等功能
达梦数据库语句句柄个数超上限或系统内存不足_第5张图片

addBatch
将给定的 SQL 命令添加到此 Statement 对象的当前命令列表中。通过调用方法 executeBatch 可以批量执行此列表中的命令。
executeBatch()将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。
通过以上的分析我将代码改写为

使得每次循环时不将会创建预编译的 SQL 语句的对象,这样便避免的句柄的增加
解决问题
附件:
1.实体类

package dm_02;

import java.io.InputStream;
import java.io.StringReader;



/**
* @类名  Testyy1.java
* @作者  li2025
* @版本  V1.0
* @日期  2020年6月30日-下午3:10:19
* @描述  
*
*/
public class Testyy1 {
	private int C1=1;
	private String C2;
	private Double C3;
	private long C4;
	private StringReader C5;
	private InputStream C6;
	public Testyy1() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Testyy1(int c1, String c2, Double c3, long c4, StringReader c5, InputStream c6) {
		super();
		C1 = c1;
		C2 = c2;
		C3 = c3;
		C4 = c4;
		C5 = c5;
		C6 = c6;
	}
	public int getC1() {
		return C1;
	}
	public void setC1(int c1) {
		C1 = c1;
	}
	public String getC2() {
		return C2;
	}
	public void setC2(String c2) {
		C2 = c2;
	}
	public Double getC3() {
		return C3;
	}
	public void setC3(Double c3) {
		C3 = c3;
	}
	public long getC4() {
		return C4;
	}
	public void setC4(long c4) {
		C4 = c4;
	}
	public StringReader getC5() {
		return C5;
	}
	public void setC5(StringReader c5) {
		C5 = c5;
	}
	public InputStream getC6() {
		return C6;
	}
	public void setC6(InputStream c6) {
		C6 = c6;
	}
	
}

2.Conect配置

package dm_02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Conn {
	Connection con=null;
	public Connection getConn(){
		String cname="dm.jdbc.driver.DmDriver";
		String url="jdbc:dm://127.0.0.1:5236?logDir=E:\\big_date\\DM&logLevel=all";//DM7的端口号为5236
		String userid="SYSDBA";
		String pwd="SYSDBA";
		
		try{
			Class.forName(cname);
			con=DriverManager.getConnection(url,userid,pwd);
			System.out.println();
		}catch(Exception e){
			System.out.println("数据库连接失败:"+e.getMessage());
		}
		
		return con;
	}
	public void disConn() throws SQLException{
		if(con!=null){
			con.close();
		}
	}
}

3.方法类

package dm_02;
import java.io.*;
import java.sql.*;
import java.util.Date;

public class Stmt {

	Connection con=null;
	Statement stmt=null;
	ResultSet rs=null;
	PreparedStatement prest=null;
	Conn connect=new Conn();
	int m=20;

	//测试建表
	public void stmt_create() throws SQLException, FileNotFoundException{
		String sql1_d = "drop table TESTYYL;";
		String sql1 = "create table TESTYYL(C1 int,C2 VARCHAR(100),C3 number(10,2),C4 timestamp,C5 clob,C6 blob);";
		con = connect.getConn();
		stmt = con.createStatement();
		try {
			stmt.executeUpdate(sql1);
		} catch (SQLException e) {
			// 表已存在则创建失败,删除表并重新创建
			stmt.executeUpdate(sql1_d);
			stmt.executeUpdate(sql1);
		}
		System.out.println("建表成功成功!");
		stmt.close();
		con.close();
		connect.disConn();
		
	}
	
	//循环插入10条记录
	public void stmt_insert() throws SQLException, FileNotFoundException{
		String sql1 = "insert into testyyl values(?,?,?,?,?,?);";
		con = connect.getConn();
		Statement stmt=con.createStatement();
		con.setAutoCommit(false);
		prest = con.prepareStatement(sql1);
		int i = 0;
		int j=12222;
		String str = "达梦数据库";  
        File  file  =  new  File("test_info\\pic.jpg");             
		long t = System.nanoTime();// 获取当期时间,单位为纳秒
		Testyy1[] testyy1s=new Testyy1[m];
		for (i = 0; i < m; i++) {
			StringReader vclob = new StringReader(str); 
			InputStream  vblob  =  new  FileInputStream(file);  
			testyy1s[i]=new Testyy1(j++, "wuhandameng", Math.random(), new Date().getTime(), vclob, vblob);
		}
		for (i = 1; i <= m; i++) {
			//prest = con.prepareStatement(sql1);
			prest.setInt(1, testyy1s[i-1].getC1());
			prest.setString(2, testyy1s[i-1].getC2());
			prest.setDouble(3, testyy1s[i-1].getC3());
			prest.setTimestamp(4, new java.sql.Timestamp(testyy1s[i-1].getC4()));
			prest.setClob(5,testyy1s[i-1].getC5() );   //也可以直接用prest.SetString("达梦数据库");
			prest.setBlob(6, testyy1s[i-1].getC6());
			prest.addBatch();
		}
		prest.executeBatch();
		con.commit();
		t = (System.nanoTime() - t) / 1000000;
		System.out.println("插入" + (i - 1) + "行记录耗时:" + t + "毫秒");
		stmt.close();
		con.close();
		connect.disConn();
	}
	

	//删除
	public void stmt_delete() throws SQLException, FileNotFoundException{
		String sql1="delete from testyyl where c1=? and c2=?";
		con=connect.getConn();
		con.setAutoCommit(false);
		prest=con.prepareStatement(sql1);
		int i = 0;
		for(i = 1; i <= m; i++){
			
			 prest.setInt(1, i);
			 prest.setString(2, "wuhandameng");
			 prest.addBatch();
			 //prest.executeBatch();
		}
		prest.executeBatch();
		con.commit();

		System.out.println("删除"+(i-1)+"条记录成功!");
		prest.close();
		con.close();
		connect.disConn();
	}
	
	public void stmt_select() throws SQLException, FileNotFoundException{
		
		String sql1="select * from testyyl;";

		con=connect.getConn();
		Statement stmt=con.createStatement();
		ResultSet rs1=stmt.executeQuery(sql1);
		
		 while(rs1.next()){
			
			System.out.println(
					rs1.getInt(1)+","+
					rs1.getString(2)+","+
					rs1.getDouble(3)+","+
					rs1.getTimestamp(4)+","+
					rs1.getString(5)+","+   //rs1.getClob(5)
					rs1.getBlob(6)         //rs1.getBytes(6)
					);
		}
		rs1.close();
		stmt.close();
		con.close();
		connect.disConn();
	}
}



4.main入口

package dm_02;
public class Dm_Demo {
	public static void main(String[] args) throws Exception{
		
			Stmt st1=new Stmt();
			//st1.stmt_delete();
			//st1.stmt_create();
			st1.stmt_insert();
			//st1.stmt_select();
			//st1.stmt_delete();
			//st1.stmt_select();
		
	}
}

更多资讯请上达梦技术社区了解: https://eco.dameng.com

你可能感兴趣的:(SQL,数据库)