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.
Related
I am working on IBM MQ Performance testing using JMeter. Currently while executing the script i am facing error message. I am able to connect this IBM MQ using RHF utility manually. But in JMeter, i am getting below error. May i know how to fix this error.
Error :
Response message:javax.script.ScriptException: com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0018: Failed to connect to queue manager 'CLDACEAPD' with connection mode 'Client' and host name '172.XX.XX.XX(1414)'.
Check the queue manager is started and if running in client mode, check there is a listener running. Please see the linked exception for more information.
Look at jmeter.log file, the full exception details should be there, look for the string which starts with Caused by and see what is the real cause of the issue.
If it's not there surround your code which establishes the connection with the queue manager into try block and populate the catch block as follows:
try {
//your code here
}
catch (Exception ex) {
log.error('Failed to connect to IBMMQ instance', ex)
}
Additional logging for IBMMQ client can be enabled by setting the following system properties:
com.ibm.msg.client.commonservices.trace.status=ON
com.ibm.msg.client.commonservices.trace.level=9
com.ibm.msg.client.commonservices.trace.outputName=/path/to/ibbmq/client.log
I have a problem with the Oracle Universal Connection Pool (UCP) implemented in a Scala application, for an Oracle Database.
It works perfectly while there's a connection to the database, but when the network has some problem for a limited period of time (the application or the database goes offline) it obviously fails to create a Connection while the problem persists, but then it doesn't manage to create new ones when the application can ping the database again. The only way to get the application work again is to restart it.
I've set up a class in which I manage the connection, and I create the pool data source with this method:
private def createConnectionPool(
connectionString: String,
username: String,
password: String
): PoolDataSource =
{
val p = PoolDataSourceFactory.getPoolDataSource()
p.setConnectionPoolName("main_ucp_pool")
p.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource")
p.setURL(connectionString)
p.setUser(username)
p.setPassword(password)
p.setInitialPoolSize(5)
p.setMinPoolSize(3)
p.setMaxPoolSize(20)
p
}
private lazy val pds = createConnectionPool('url', 'username', 'pass')
Then, every time I need a database connection, I get it through this method invocation:
pds.getConnection()
Am I missing something in the code, or is it true that the pool data source should retry to establish a connection to the database when the getConnection method is invoked, even after a network problem?
In other words, if it fails to create the connection when the network goes down, the second time, if the application can now ping the database, the connection must be established?
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()
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);
}
}