postgresql error: canceling statement due to user request - java

What causes this error in postgresql?
org.postgresql.util.PSQLException: ERROR: canceling statement due to user request
My Software Versions:
PostgreSQL 9.1.6 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2), 64-bit".
My postgresql driver is: postgresql-9.2-1000.jdbc4.jar
Using java version: Java 1.7
Clue: My postgresql database is on a solid state hard drive and this error happens randomly and sometimes not at all.

We have figured out the the cause of this issue. It's explained by buggy implementation of setQueryTimeout() in latest JDBC drivers 9.2-100x. It might not happen if you open / close connection manually, but very often happens with connection pooling in place and autocommit set to false. In this case, setQueryTimeout() should be called with non-zero value (as an example, using Spring framework #Transactional( timeout = xxx ) annotation).
It turns out, whenever SQL exception is raised during the statement execution, the cancellation timer hasn't been cancelled and stays alive (that's how it is implemented). Because of pooling, connection behind is not closed but is returned to the pool.
Later on, when cancellation timer triggers, it randomly cancels the query currently associated with the connection this timer has been created with. At this moment, it's a totally different query which explains the randomness effect.
The suggested workaround is to give up on setQueryTimeout() and use PostgreSQL configuration instead (statement_timeout). It doesn't provide same level of flexibility but at least always works.

This assumes that the race condition bug in the jdbc jar file for postgresql is responsible for the above error.
Workaround 1, refresh connection to database periodically
One workaround is to close the connection to the database and create a new connection to the database periodically. After every few thousand sql statements just close the connection and re-create it. Then for some reason this error is no longer thrown.
Workaround 2, turn on logging
If you turn on logging at the JDBC driver level when you are setting the driver, then in some situations the race condition problem is neutralized:
Class.forName("org.postgresql.Driver");
org.postgresql.Driver.setLogLevel(org.postgresql.Driver.DEBUG);
Workaround 3, catch the exception and re-initialize connection
You could also try catching the specific exception, re-initializing the connection and trying the query again.
Workaround 4, wait until postgresql jdbc jar comes out with a bug fix
I think the problem may be associated with the speed of my SSD hard drive. If you get this error, please post how to reproduce it consistently here, there are devs very interested in squashing this bug.

If you are getting this error without using transactions
The user has requested the statement be cancelled. The statement is doing exactly what it is told to do. The question is, who requested this statement be cancelled?
Look at every line in your code which prepares the SQL for execution. You could have some method that applies to the statement which cancels the statement under some circumstances, like this:
statement = conn.createStatement();
conn.setAutoCommit(true);
statement.setQueryTimeout(25);
my_insert_statement.setString(1, "moobars");
my_insert_statement.executeUpdate();
statement.close();
In my case, what happened was I had set the query timeout to 25 seconds, and when the insert took longer than that. It passed the 'canceling statement due to user request' exception.
If you are getting this error while using transactions:
If you receive this Exception, double check all your code that does SQL transactions.
If you have a query that is in a transaction and you forget to commit, and then you use that connection to do something else where you operate as if you are not in a transaction, there could be undefined behavior which produces this Exception.
Make sure all code that does a transaction is cleaning up after itself. Make sure the transaction begins, work is done, more work is done, and the transaction is rolled back or committed, then make sure the connection is left in the autocommit=true state.
If this is your problem, then the Exception is not thrown where you have forgotten to clean up after yourself, it happens somewhere long after you have failed to clean up after a transaction, making this an elusive exception to track down. Refreshing the connection (closing it and getting a new one) will clear it up.

In addition to Eric's suggestions, you can see statement cancels when:
An adminisrator or another connection logged in as the same user uses pg_cancel_backend to ask your session to cancel its current statement
The administrator sends a signal to the PostgreSQL backend that's running your statement
The administrator requests a fast shutdown or restart of the PostgreSQL server
Check for cron jobs or load management tools that might be cancelling long-running queries.

Related

How to SET LOCK MODE in java application

I am working on a Java web application that uses Weblogic to connect to an Informix database. In the application we have multiple threads creating records in a table.
It happens pretty often that it fails and the following error is thrown:
java.sql.SQLException: Could not do a physical-order read to fetch next row....
Caused by: java.sql.SQLException: ISAM error: record is locked.
I am assuming that both threads are trying to insert or update when the record is locked.
I did some research and found that there is an option to set the database that instead of throwing an error, it should wait for the lock to be released.
SET LOCK MODE TO WAIT;
SET LOCK MODE TO WAIT 17;
I don't think that there is an option in JDBC to use this setting. How do I go about using this setting in my java web app?
You can always just send that SQL straight up, using createStatement(), and then send that exact SQL.
The more 'normal' / modern approach to this problem is a combination of MVCC, the transaction level 'SERIALIZABLE', retry, and random backoff.
I have no idea if Informix is anywhere near that advanced, though. Modern DBs such as Postgres are (mysql does not count as modern for the purposes of MVCC/serializable/retry/backoff, and transactional safety).
Doing MVCC/Serializable/Retry/Backoff in raw JDBC is very complicated; use a library such as JDBI or JOOQ.
MVCC: A mechanism whereby transactions are shallow clones of the underlying data. 2 separate transactions can both read and write to the same records in the same table without getting in each other's way. Things aren't 'saved' until you commit the transaction.
SERIALIZABLE: A transaction level (also called isolationlevel), settable with jdbcDbObj.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); - the safest level. If you know how version control systems work: You're asking the database to aggressively rebase everything so that the entire chain of commits is ordered into a single long line of events: Each transaction acts as if it was done after the previous transaction was completed. The simplest way to implement this level is to globally lock all the things. This is, of course, very detrimental to multithread performance. In practice, good DB engines (such as postgres) are smarter than that: Multiple threads can simultaneously run transactions without just being frozen and waiting for locks; the DB engine instead checks if the things that the transaction did (not just writing, also reading) is conflict-free with simultaneous transactions. If yes, it's all allowed. If not, all but one simultaneous transaction throw a retry exception. This is the only level that lets you do this sequence of events safely:
Fetch the balance of isaace's bank account.
Fetch the balance of rzwitserloot's bank account.
subtract €10,- from isaace's number, failing if the balance is insufficient.
add €10,- to rzwitserloot's number.
Write isaace's new balance to the db.
Write rzwitserloot's new balance to the db.
commit the transaction.
Any level less than SERIALIZABLE will silently fail the job; if multiple threads do the above simultaneously, no SQLExceptions occur but the sum of the balance of isaace and rzwitserloot will change over time (money is lost or created – in between steps 1 & 2 vs. step 5/6/7, another thread sets new balances, but these new balances are lost due to the update in 5/6/7). With serializable, that cannot happen.
RETRY: The way smart DBs solve the problem is by failing (with a 'retry' error) all but one transaction, by checking if all SELECTs done by the entire transaction are not affected by any transactions that been committed to the db after this transaction was opened. If the answer is yes (some selects would have gone differently), the transaction fails. The point of this error is to tell the code that ran the transaction to just.. start from the top and do it again. Most likely this time there won't be a conflict and it will work. The assumption is that conflicts CAN occur but usually do not occur, so it is better to assume 'fair weather' (no locks, just do your stuff), check afterwards, and try again in the exotic scenario that it conflicted, vs. trying to lock rows and tables. Note that for example ethernet works the same way (assume fair weather, recover errors afterwards).
BACKOFF: One problem with retry is that computers are too consistent: If 2 threads get in the way of each other, they can both fail, both try again, just to fail again, forever. The solution is that the threads twiddle their thumbs for a random amount of time, to guarantee that at some point, one of the two conflicting retriers 'wins'.
In other words, if you want to do it 'right' (see the bank account example), but also relatively 'fast' (not globally locking), get a DB that can do this, and use JDBI or JOOQ; otherwise, you'd have to write code to run all DB stuff in a lambda block, catch the SQLException, check the SqlState to see if it is indicating that you should retry (sqlstate codes are DB-engine specific), and if yes, rerun that lambda, after waiting an exponentially increasing amount of time that also includes a random factor. That's fairly complicated, which is why I strongly advise you rely on JOOQ or JDBI to take care of this for you.
If you aren't ready for that level of DB usage, just make a statement and send "SET LOCK MDOE TO WAIT 17;" as SQL statement straight up, at the start of opening any connection. If you're using a connection pool there is usually a place you can configure SQL statements to be run on connection start.
The Informix JDBC driver does allow you to automatically set the lock wait mode when you connect to the server.
Simply pass via the DataSource or connection URL the following parameter
IFX_LOCK_MODE_WAIT=17
The values for JDBC are
(-1) Wait forever
(0) not wait (default)
(> 0) wait this many seconds
See https://www.ibm.com/support/knowledgecenter/SSGU8G_14.1.0/com.ibm.jdbc.doc/ids_jdbc_040.htm
Connection conn = DriverManager.getConnection ( "jdbc:Informix-sqli://cleo:1550:
IFXHOST=cleo;PORTNO=1550;user=rdtest;password=my_passwd;IFX_LOCK_MODE_WAIT=17";);

When Database Mysql crashes , how do i know in java

I am using J2EE and a Mysql database and making a connection using JDBC. I want to know when the database crashes and how to handle it. Is it that the only way to check the database is to see if the connections establish successfully? Or there is other way?
You can't and shouldn't need to know. As far as your program is concerned, either everything works perfectly or you can't get a connection.
The program has to behave correctly if a connection can't be acquired, which in most cases probably involves some form of error display and ceasing of operations. Naturally you'll want to have some form of monitoring so that someone will know to check what's wrong with the database, but it's not your program's responsibility.
There are actually a lot of things that can go wrong in a database that might constitute a crash, a major failure or a partial failure. A table could get dropped by an admin, you could run out of space, etc, etc. These might allow you to get a connection or they might not.
It is probably going to be very difficult to distinguish between what constitutes a major failure (database down) and what is a partial failure that might allow the system to continue.
Obviously, if you can't connect to the database, you can't do much with your application. That might indicate the database has "crashed", but it could also be a network problem if your database in on another server. It doesn't really matter.
Most applications that I have worked on don't do much in terms of checking for major failures. But there are a few of strategies that might help:
Have some "sanity checks" (e.g., query a known table). If the sanity checks fail, you have a critical problem.
Have an error count. If more than a certain number of errors occurred in a given time, you have a critical problem.
How do I know in my Java code when my DB crashes?
As of JDBC 4.1 (JavaSE 7) there is the Connection.setNetworkTimeout(Executor, int) method which make JDBC operations cease execution and throw an SQLException if they take longer than the timeout you set.
To use this mechanism, set the network timeout to a number of milliseconds which you want to be the maximum amount of time you will wait to hear back from the DB. If any operations takes longer than the timeout you set, it will cease waiting and the method will throw an SQLException.
An example of how setNetworkTimeout could be used:
Connection conn = // get your connection however
conn.setNetworkTimeout(Executors.newSingleThreadExecutor(),
10 * 1000); // 10s timeout
Statement stmt = conn.createStatement();
// suppose DB crashes at this point in time
try {
stmt.execute("SOME SQL HERE");
} catch (SQLException sqle) {
// could be from network timeout,
// but could also be caused by something else
// You can check what your JDBC driver does
}
As you can see with this example, the fact that network timeouts only throw a SQLException makes the mechanism harder to work with. I really wish the architects of JDBC 4.1 had decided to require some subclass of SQLException be thrown so that there was a portable way of telling when a network timeout occurs. Something like SQLNetworkTimeoutException as a subclass of SQLException would have been nice.
In any case, your best bet for checking whether or not your SQLException was caused from a network timeout is by checking the message String on the SQLException, but be a bit careful doing this as different JDBC drivers will have different messages for network timeouts.
Another thing you could try in addition to or besides network timeout is checking for SQLNonTransientException. Typically the exception that will occur when there is some sort of catastrophic DB failure is the SQLNonTransientException which is the subclass of SQLException.
Essentially this exception means "something went wrong that is outside of the control of your code or the JDBC driver's". So generally when you see this, it's because of a DB failure or network failure.
How do I handle a DB failure once I know something went wrong?
This part is a bit tricky, especially since so many things can go wrong with a DB (it could have crashed, the network could be down/slow, etc).
Option A: Show that something went wrong
In most cases I've seen, the way to "handle" this sort of failure is to acknowledge it and just present it to the user.
Option B: Retry and/or failover
Another option is doing a fixed number of retries and/or failing over to a backup database. Failing over to a backup db can be tricky, and typically this is only done if you have some sort of middleware do it for you.

What happens to MySQL connection when internet connection is lost?

My application-server has a connection to a MySQL database. This connection is open 24/7.
Lets say my internet were to crash, or I were to block the port 3306.
Will JDBC throw an error? And if not, how should I be handling this kind of problem?
The reason I'm asking this is because I've had cases before where the MySQL connection randomly stopped working, but wasn't closed, which caused clients to time out.
You will get a MySQLNonTransientConnectionException or CommunicationsException. Typically, for program safety you either want to:
Open/close connections as necessary
Re-open when connection is closed
I recommend the former personally, especially when the database is user-specified (some mysql setups have a connection timeout).
Edit:
I did seem to forget to mention connection pools, per #ThorbjørnRavnAndersen , but that is also a viable solution. I personally don't do that myself, using an instantiable SQL connection per threaded operation.
Personally, I throw any database calls into try/catch blocks, because there's always the potential for issues to arise. You'll want to set some default values in the catch block, and if it happens to land on these defaults for whatever reason, display the end user some sort of (ideally pretty) error message.
Running a SQL query isn't always guaranteed to pull back any sort of results either...any number of things could go wrong - the server could be down, the connection could be so saturated that it's not able to pull the results in a timely manner, it could be sitting in the dead center of a backup of sorts too....These things have to always be accounted for, that's why I recommend doing it the way described above.
Lastly, to answer your question, yes, JDBC will in fact throw an error - under any of these circumstances.

How to know why a jdbc connection became invalid

I would like to know friends, when a jdbc connection becomes invalid, it could be that it was closed intentionally, or some transaction made it invalid and closed it, is there a way to know what exactly made the connection invalid, is there any trace left on the connection that I can get and check.
I am faced with a situation where I have to detect a server that has gone offline, how I do this is; any operation that tries to borrow a connection from the connection pool, check if that connection is valid. If it is not, and if the reason for it not being valid is that it failed to connect to the database, then fire a propertychange and notify any subscriber to the change, the subscriber will then popup a dialog to block all operations and start querying the database every 5 seconds to check if it is back. Hope I made my situation clear
Better you could use a connection pooling library that will validate connection on behalf of you. During database operation it will automatically test the connection health and make a new connection if the existing one is invalid.
For C3P0 connection pooling library, please check the following document:
http://www.mchange.com/projects/c3p0/#configuring_connection_testing
Typically when you attempt to use a stale connection, for example by issuing a simple SQL statement as suggested by #PeterLawrey, an SQLException will be thrown, containing the details of what is wrong, if they are at all available to the driver. Catch the exception and analyze what is returned by its getErrorCode() and getSQLState() methods. Keep in mind that, while SQLSTATE values are standardized, they are not very granular, while vendor error codes may provide more information but will differ when connected to different database platforms.

JBoss AS 5 database connection pool re-connect routine for MS SQL Server

I'd like to come up with the best approach for re-connecting to MS SQL Server when connection from JBoss AS 5 to DB is lost temporarily.
For Oracle, I found this SO question: "Is there any way to have the JBoss connection pool reconnect to Oracle when connections go bad?" which says it uses an Oracle specific ping routine and utilizes the valid-connection-checker-class-name property described in JBoss' Configuring Datasources Wiki.
What I'd like to avoid is to have another SQL run every time a connection is pulled from the pool which is what the other property check-valid-connection-sql basically does.
So for now, I'm leaning towards an approach which uses exception-sorter-class-name but I'm not sure whether this is the best approach in the case of MS SQL Server.
Hoping to hear your suggestions on the topic. Thanks!
I am not sure it will work the way you describe it (transparently).
The valid connection checker (this can be either a sql statement in the *ds.xml file or a class that does the lifting) is meant to be called when a connection is taken from the pool, as the db could have closed it while it is in the pool. If the connection is no longer valid,
it is closed and a new one is requested from the DB - this is completely transparent to the application and only happens (as you say) when the connection is taken out of the pool. You can then use that in your application for a long time.
The exception sorter is meant to report to the application if e.g. ORA-0815 is a harmless or bad return code for a SQL statement. If it is a harmless one it is basically swallowed, while for a bad one it is reported to the application as an Exception.
So if you want to use the exception sorter to find bad connections in the pool, you need to be prepared that basically every statement that you fire could throw a stale-connection Exception and you would need to close the connection and try to obtain a new one. This means appropriate changes in your code, which you can of course do.
I think firing a cheap sql statement at the DB every now and then to check if a connection from the pool is still valid is a lot less expensive than doing all this checking 'by hand'.
Btw: while there is the generic connection checker sql that works with all databases, some databases provide another way of testing if the connection is good; Oracle has a special ping command for this, which is used in the special OracleConnectionChecker class you refer to. So it may be that there is something similar for MS-SQL, which is less expensive than a simple SQL statement.
I used successfully background validation properties: background-validation-millis from https://community.jboss.org/wiki/ConfigDataSources
With JBoss 5.1 (I don't know with other versions), you can use
<valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MSSQLValidConnectionChecker</valid-connection-checker-class-name>

Categories