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);
}
}
Related
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'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()
Does SQL Azure allow 3-rd party connection pool like HikariCP or BoneCP?
We configured HikariCP it works when we just run app but later db doesnt response on request. Is it HikariCP issue or it's common connection poool issue and no need spending more time on investigation?
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(50);
config.setDriverClassName(env.getProperty("jdbc.driverClassName"));
config.setJdbcUrl(env.getProperty("jdbc.url"));
config.setUsername(env.getProperty("jdbc.user"));
config.setPassword(env.getProperty("jdbc.pass"));
config.addDataSourceProperty("cachePrepStmts", env.getProperty("jdbc.cachePrepStmts"));
config.addDataSourceProperty("prepStmtCacheSize", env.getProperty("jdbc.prepStmtCacheSize"));
config.addDataSourceProperty("prepStmtCacheSqlLimit", env.getProperty("jdbc.prepStmtCacheSqlLimit"));
config.addDataSourceProperty("useServerPrepStmts", env.getProperty("jdbc.useServerPrepStmts"));
See this SQL Azure page re: Connection Constraints.
Maximum allowable durations are subject to change depending on the resource usage.
A logged-in session that has been idle for 30 minutes will be terminated
automatically. We strongly recommend that you use the connection pooling and
always close the connection when you are finished using it so that the unused
connection will be returned to the pool. For more information about connection
pooling, see Connection Pooling.
See if any of these errors match up to your logs. Search that page for "terminated" and "busy" to find error codes that might be relevant to your issue.
I would suggest setting the maxLifetime property in HikariCP to 15 minutes, and the idleTimeout to 2 minutes.
There is nothing on the SQL Azure side that would prohibit you from using a 3rd party connection pool. My guess is that the connection failed between the server and the client and the client didn't remove the connection from the pool.
Moving forward, I'd ensure that whichever 3-rd part connection pool you end up using tests that the connection exists before taking it out of the pool for use.
Hope that helps.
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.
My application needs to authenticate all session on the DB via a trusted procedure (that sets some values in the session context). Currently this procedure is called for each new session just after it is opened.
I'd now like to improve this by removing unneeded round-trips. Connections from the connection pool which were used (and authenticated) before don't need to call the procedure again because the session context variables are still set on the server.
But I can't find a way to identify reused connections. Is there any way (which of course doesn't need a round-trip too)?
Architecture: Multiple client applications use the same DB account (a read-only account with synonyms to the real schema) to connect. After the connection it is required that each new session calls an authentication procedure to set some session context variables. These context variables are checked on select/insert/update/delete by Oracle FGAC (virtual private database).
My code:
OracleConnection conn = new OracleConnection();
conn.ConnectionString = _connectionString;
conn.Open();
if (true) { // TODO: Identify not yet authenticated connections.
using (OracleCommand cmd = new OracleCommand("authentication.login", conn)) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("i_user_id", OracleDbType.Int64).Value = _userId;
cmd.Parameters.Add("i_role_id", OracleDbType.Int64).Value = _roleId;
cmd.ExecuteNonQuery();
}
}
You could create a connection pool for your oracle connections.
And each connection you create could be inserted with a some key (using conn.setSessionInfo(key)) that can be verified later when you get the connection back.
The key can be a any thing of your choice or maybe a hashkey you generate.
I finally found an answer that clearly states that this isn't possible: ODP.NET connection pooling: How to tell if a connection has been used
You should clear all contexts and reset all packages anyway when you get a connection from a connectionpool. Add this authentication to your initialization.
Preparing an Oracle Connection after being retrieved from a ConnectionPool
I'm not clear what your authentication is doing - verifying that the connection comes from your app? - and whether you're passing anything to your procedure. Could you consider using a logon trigger to call your procedure from the DB side, only for the user your pool is using, as the session is created?