我有以下代码被其他应用程序调用(我无法更改)从数据库中读取。 经常在循环中调用该方法并对DB进行DOS操作。 在数据库中,我可以看到有许多连接被打开...增加到几百...而且由于负载导致数据库崩溃。
// Called in a loop
private <T> T execute(String query, PostProcessor<T> postProc, PreProcessor preProcs) throws OperationFailedException {
try (Connection conn
= Objects.requireNonNull(dataSourceRef.get(), "No Connection").getConnection();
PreparedStatement smt = conn.prepareStatement(query)) {
preProc.process(smt);
return postProc.process(smt.executeQuery());
} catch (SQLException e) {
throw new OperationFailedException(e.getMessage(), e);
}
}
日期源在之前被初始化...
// class variable
// AtomicReference<PooledDataSource> dataSourceRef = new AtomicReference<PooledDataSource>();
// Init method
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass(config.getConnectionDriver());
cpds.setJdbcUrl(config.getConnectionString());
cpds.setUser(config.getConnectionUser());
cpds.setPassword(config.getConnectionPassword());
// cpds.setMaxPoolSize(10);
dataSourceRef.getAndSet(cpds);
我的问题为什么会发生这种情况。 我认为由于池不是每个查询都应该使用新的连接。同样通过设置最大池大小,这不起作用。
我尝试使用try-catch-finally构建并在使用后关闭stm和conn。 (正如我在某处看到的那样,在高负载情况下最终可能被称为延迟...我可能就是这种情况)
但仍然为什么游泳池大小超过?在继续之前,如何在连接可用之前限制并阻止该方法?
在c3p0中的连接池期间,您必须考虑一些选项。这些是在qazxsw poi文件下面给出的:
application.property
在这里,db.driver: oracle.jdbc.driver.OracleDriver // for Oracle
db.username: YOUR_USER_NAME
db.password: YOUR_USER_PASSWORD
db.url: DATABASE_URL
minPoolSize:5 // number of minimum poolSize
maxPoolSize:100 // number of maximum poolSize
maxIdleTime:5 // In seconds. After that time it will realease the unused connection.
maxStatements:1000
maxStatementsPerConnection:100
maxIdleTimeExcessConnections:10000
是主要观点。它定义了释放未使用连接的秒数。它排在第二位。
另一个是maxIdleTime
。它定义了在空闲模式下它将保持多少连接。
另一个是minPoolSize
。它定义了在加载模式下它将保持的最大连接数。
现在,你如何配置maxPoolSize
?这是代码:
ComboPooledDataSource
有关详细信息,请查看@Bean
public ComboPooledDataSource dataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass(env.getProperty("db.driver"));
dataSource.setJdbcUrl(env.getProperty("db.url"));
dataSource.setUser(env.getProperty("db.username"));
dataSource.setPassword(env.getProperty("db.password"));
dataSource.setMinPoolSize(Integer.parseInt(env.getProperty("minPoolSize")));
dataSource.setMaxPoolSize(Integer.parseInt(env.getProperty("maxPoolSize")));
dataSource.setMaxIdleTime(Integer.parseInt(env.getProperty("maxIdleTime")));
dataSource.setMaxStatements(Integer.parseInt(env.getProperty("maxStatements")));
dataSource.setMaxStatementsPerConnection(Integer.parseInt(env.getProperty("maxStatementsPerConnection")));
dataSource.setMaxIdleTimeExcessConnections(10000);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
。这里我添加了实际的实现
编辑(获取连接)
您可以使用以下方式获得连接:
this thread
你如何获得EntityManager?
Session session = entityManager.unwrap(Session.class);
session.doWork(connection -> doSomeStuffWith(connection));
希望这会帮助你。
谢谢 :)