I'm use Hikari jdbc connection pool.
when execute statement witch produce an exception ( for example by network is broken). as following:
try{
Connection con = pool.getConnection();
con.executeQuery("....");
}catch(Exception e){
con.close();
}
does con.close will evict the broken connection, instead of release it to the pool.
if the broken connection is released to pool. it maybe got by following request of getConnection.
If your driver is JDBC4 compatible (and supports Connection.isValid()) the validation of the connection is done via this API per default).
Otherwise you may set the connectionTestQuery to be performed for the validation.
See also this discussion and the source code.
Use con.close in finally block, otherwise in the catch block you must ask first if con != null for avoid the exception produced in the catch block. Other alernative could be enclose, con.close() in other try{}catch{} block. Hope this help.
You should consider try-with-resource:
try(Connection con = pool.getConnection()) {
DO SOMETHING WITH CONNECTION
}catch(Exception e){
e.printStackTrace();
}
this will guarantee the connection is given back to the pool. Checking if a connection is valid is a task for the pool, not for your code. You can configure the pool to check your connection with the connectionTestQuery property - so there's that.
If you are using try-with-resource and if network is broken, HikariCP most likely will close connection, not recycle.
from HikariCP source, if there is such exception in connection.close(), it is closing connection in checkException()
Related
I have a verticle, which consumes a message from the event bus and processes it. I have a question as to when the JDBC connection should be closed. There are 2 approaches
Closing the connection once the message is processed. But this will be very expensive because I will open/close connection every time.
Trust that vertx will close the connection when the verticle is stopped/undeployed (which is literally never) and that there wont be any memory leaks as long as the connection is open. I will open the connection in the start() method, so that whenever there is a message it available.
On the other hand, If I have an elastic search backend and I am using the elastic search SDK, which has a specific method to close the client, when should the connection be really closed?
Use a connection pool, that will take away most of the cost of closing/opening connections. When using a connection pool, closing the connection returns it to the connection pool for re-use.
The basic usage pattern is:
try (Connection connection = dataSource.getConnection()) {
// use connection
}
At the end of the block the connection is closed, which - if dataSource has a connection pool - will make it available for re-use.
You can always put your clean up code in Stop() method of Verticle interface. It will be called when the verticle starts it's un-deploy procedure.
See Vert.x Docs
I am using Oracle UCP JDBC, and the following method is for getting a connection from a connection pool.
private static PoolDataSource poolDataSource;
....
static synchronized Connection createConnection() throws SQLException {
if (poolDataSource == null) {
poolDataSource = PoolDataSourceFactory.getPoolDataSource();
poolDataSource.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
poolDataSource.setURL(url);
poolDataSource.setUser(user);
poolDataSource.setPassword(password);
poolDataSource.setInitialPoolSize(1);
poolDataSource.setMinPoolSize(1);
poolDataSource.setMaxPoolSize(10);
}
Connection connection = poolDataSource.getConnection();
return connection;
}
I know that there is Connection.isValid() method to check whether a connection obtained from the pool is valid. But if isValid() returns false, what can I do? How do I force the connection pool to re-establish its connection?
Also, note that in our test environment, we are not using RAC (Real Application Clusters), but in production environment, we do have RAC. I have read that for RAC, we need to do some configuration in the codes in order for RAC to work.
Is it possible to have the same codes for RAC and non-RAC environments so that invalid connections in the pool re-established?
Thanks in advance.
If your database is up and running then isValid() will return true indicating that app can connect to the DB. However, in the production system, there will be many nodes and if one of the nodes is down then UCP will get the connection from other nodes. Let me know if this clarifies your question.
I am using C3P0NativeJdbcExtractor to extract the native JDBC connection as below.
public Connection getNativeConnection() throws SQLException{
C3P0NativeJdbcExtractor nativeJbdc;
nativeJbdc = new C3P0NativeJdbcExtractor();
return nativeJbdc.getNativeConnection(dataSource.getConnection());
}
Note that the data source here is obtained of a C3P0 Connection Pool. When I do a Connection.close() returned on this method, it is actually closing the connection instead of returning to the pool.
However if we close the unwrapped connection, then it is returned to the Pool.
Is there is a reason to why closing the wrapped connection here is failing to return the connection to the pool?
A connection pool like c3p0, holds a collection of physical ('native') connections created by a JDBC driver. When you ask it for a connection, it wraps that physical connection in a proxy, also known as the logical connection.
That proxy will intercept certain methods like Connection.close(). For close() instead of closing the connection, it invalidates the logical connection so it behaves as a closed connection, and it returns the physical connection to the connection pool.
Your code extracts the physical connection from the logical connection, and returns that instead, so if you call close() on that, you actually close the connection to the database instead of returning it to the pool.
You should almost never have a reason to extract the native connection like that. The only reason is when you need access to driver-specific features. You should try to use standard JDBC as much as possible, and only unwrap to access driver-specific features when you really need to.
When you call close(), make sure you call close() on the logical connection that you received from the connection pool, not on the unwrapped physical connection.
Hi I have problem with enlist to distributed transaction after database restart.
My environment:
Windows 7 x64 with SP1
Oracle Database 11g Express Edition
ODP.NET 4.112.3.0
My program:
const string connectionString = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=LOCALHOST)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XE)));User Id=system;Password=sasa;";
static void Main(string[] args)
{
using (TransactionScope scope = new TransactionScope())
{
while (true)
{
using (OracleConnection connection = new OracleConnection(connectionString))
{
try
{
connection.Open();
Console.WriteLine("Connection opened");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Thread.Sleep(1000);
}
}
}
All works great after application start. When I start stopping database I get NRE and some exception telling me that database shutdown is in progress. After start it again i'm receiving error - Unable to enlist in a distributed transaction. Connection opened is no longer printed.
Output:
Connection opened
Connection opened
Connection opened
Connection opened
Connection opened
-- here I'm stopping database
ORA-12518: TNS:listener could not hand off client connection
ORA-12528: TNS:listener: all appropriate instances are blocking new connections
-- here database is stopped I suppose
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
-- here I'm starting database again
ORA-12528: TNS:listener: all appropriate instances are blocking new connections
ORA-1033: ORACLE initialization or shutdown in progress
Unable to enlist in a distributed transaction
Unable to enlist in a distributed transaction
Unable to enlist in a distributed transaction
Unable to enlist in a distributed transaction
Unable to enlist in a distributed transaction
...
What is the reason of that behavior?
How to diagnose what's happen?
You have an invalid test. You are looping inside the context of a single transaction. When the database goes down any in-progress distributed transaction is aborted. Your loop is trying to bring up a new connection under that already-dead transaction.
I'm not sure exactly what you are trying to test but moving the TransactionScope inside of the while loop should fix it.
When connecting to oracle server from .NET application using ADO.NET for oracle, even if i closed the connection, the connection remains inactive at the Oracle server, so new connections could not be established because of the sessions per user limitation, is there is any way to make sure that all connections are closed? from Oracle server or from .NET application.
Thanks in advance
Could it be the connections stay open for a while due to connection pooling? Can you please paste some code showing how you close the connections? Also are you using ODP.NET or the Microsoft supplied classes?
You could try turning connection pooling off (add ;Pooling=false to the connection string in ODP.NET) to see if your issue is caused as a consequence of using it (just be aware that creating a new physical connection to the DB is an expensive operation, so you probably actually don't want to turn off connection pooling permantly).
Something similar to:
using (OracleConnection connection = new OracleConnection(connectionString))
{
OracleCommand command = new OracleCommand(queryString);
command.Connection = connection;
try
{
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}