I have a GUI which allows users to run long running queries. Sometimes, the users regret running the queries and would like to cancel them. The queries are running using iBATIS against an Oracle database, and I know that the java.sql.Statement interface defines a cancel method that might or might not be implemented by the driver. So my question is, is it possible to use iBATIS to invoke this method to cancel the query (given the right driver), or is there any other way of aborting an ongoing long running query.
Well,
I guess that once the got to the DB server, cancelling it is really a "DB vendor specific" issue.
If your requirement is to cancel the query, when it comes to your application
(i.e - if it reaches the Oracle DB server, and is run there, you are fine, as long as you will not get the result), consider using the Future interface which has a cancel method.
You can submit a "Callable" to run your query, and it will return a proper object of type which is an implementation.
If you need to abort - just use the "cancel" method of the future object.
You can also check using "isCanceled" to see if submission was cancelled, and make proper treatment at your code.
Related
I have implemented an Android Room Database in my application. My understanding is that the Room Database interactions are to be run in the background independent of the the UI thread. If my application takes actions based on the results of a query to the database, what is the best design technique to ensure that the results of the query have completed before the executing additional code.
What I am experiencing in testing is that the query is completing well after my code continues after the submission of the query (duh!!). If a query result is depended upon for continuing execution of the program, can I tell Room to not run the query in the background and suspend running a next line of code until results have been returned.
what is the best design technique to ensure that the results of the query have completed before the executing additional code
Step #1: Have your Room DAO expose a reactive API (e.g., LiveData, RxJava, Kotlin coroutines)
Step #2: React to the results of those API calls and advance in your app at that point (e.g., from an Observer of the LiveData)
I'm trying to better understand what will happen if multiple threads try to execute different sql queries, using the same JDBC connection, concurrently.
Will the outcome be functionally correct?
What are the performance implications?
Will thread A have to wait for thread B to be completely done with its query?
Or will thread A be able to send its query immediately after thread B has sent its query, after which the database will execute both queries in parallel?
I see that the Apache DBCP uses synchronization protocols to ensure that connections obtained from the pool are removed from the pool, and made unavailable, until they are closed. This seems more inconvenient than it needs to be. I'm thinking of building my own "pool" simply by creating a static list of open connections, and distributing them in a round-robin manner.
I don't mind the occasional performance degradation, and the convenience of not having to close the connection after every use seems very appealing. Is there any downside to me doing this?
I ran the following set of tests using a AWS RDS Postgres database, and Java 11:
Create a table with 11M rows, each row containing a single TEXT column, populated with a random 100-char string
Pick a random 5 character string, and search for partial-matches of this string, in the above table
Time how long the above query takes to return results. In my case, it takes ~23 seconds. Because there are very few results returned, we can conclude that the majority of this 23 seconds is spent waiting for the DB to run the full-table-scan, and not in sending the request/response packets
Run multiple queries in parallel (with different keywords), using different connections. In my case, I see that they all complete in ~23 seconds. Ie, the queries are being efficiently parallelized
Run multiple queries on parallel threads, using the same connection. I now see that the first result comes back in ~23 seconds. The second result comes back in ~46 seconds. The third in ~1 minute. etc etc. All the results are functionally correct, in that they match the specific keyword queried by that thread
To add on to what Joni mentioned earlier, his conclusion matches the behavior I'm seeing on Postgres as well. It appears that all "correctness" is preserved, but all parallelism benefits are lost, if multiple queries are sent on the same connection at the same time.
Since the JDBC spec doesn't give guarantees of concurrent execution, this question can only be answered by testing the drivers you're interested in, or reading their source code.
In the case of MySQL Connector/J, all methods to execute statements lock the connection with a synchronized block. That is, if one thread is running a query, other threads using the connection will be blocked until it finishes.
Doing things the wrong way will have undefined results... if someone runs some tests, maybe they'll answer all your questions exactly, but then a new JVM comes out, or someone tries it on another jdbc driver or database version, or they hit a different set of race conditions, or tries another platform or JVM implementation, and another different undefined result happens.
If two threads modify the same state at the same time, anything could happen depending on the timing. Maybe the 2nd one overwrites the first's query, and then both run the same query. Maybe the library will detect your error and throw an exception. I don't know and wouldn't bother testing... (or maybe someone already knows or it should be obvious what would happen) so this isn't "the answer", but just some advice. Just use a connection pool, or use a synchronized block to ensure problems don't happen.
We had to disable the statement cache on Websphere, because it was throwing ArrayOutOfBoundsException at PreparedStatement level.
The issue was that some guy though it was smart to share a connection with multiple threads.
He said it was to save connections, but there is no point multithreading queries because the db won't run them parallel.
There was also an issue with a java runnables that were blocking each others because they used the same connection.
So that's just something to not do, there is nothing to gain.
There is an option in websphere to detect this multithreaded access.
I implemented my own since we use jetty in developpement.
I have not been able to find documentation of oracle.net.ns.Packet.recieve() method anywehre. Is this method only invoked on select queries ? or is it also invoked on insert update etc. ?
My application is spending majority of it's time in this method. What can I do to improve performance ?
It is invoked when data is being transferred between two processes. The most usual example is when a client is accessing a remote database and performs DML (select, insert, update, delete). Although the method is invoked in all these cases, it should occur with higher frequencies in case of SELECTs.
If the amount of data being transferred over the network doesn't justify the time spent on this method or if the method is invoked too often, you might want to take a look at this document and play with the SDU size:
http://docs.oracle.com/cd/E11882_01/network.112/e41945/performance.htm#NETAG014
If you're running a 10g database, this is the appropriate document:
http://docs.oracle.com/cd/B14117_01/network.101/b10775/performance.htm
Is it possible to abort an insert ... select clause from Java ? Using either JDBC or Hibernate, it doesn't matter. The DB is Oracle.
I reckon it's not possible because there is a single DB call and the process is running in Oracle, not the JVM.
Oracle OCI (C driver) provides an OCIBreak() function. It's even thread-safe and you can call it from any bg thread, while the main thread is using the same connection.
Maybe that Statement.cancel() does the same thing.
This OCIBreak() requires round trip to DB server (i.e. the network must be functional) and then the main thread receives an error:
java.sql.SQLException: ORA-01013: user requested cancel of current operation
You should be able to mark this exception as non-critical on JBOSS level (using ExceptionSorter).
PS: I'm really curious if this could be called from hibernate. As JPA leaves many long running queries on our DB servers.
Say we have a database query that takes 20seconds to run (the user runs it by clicking a button on HTML page in a browser).
The user gets impatient and only after 10seconds he refreshes his browser, only to run a new query.
How do I stop the first running database query (or prevent the second one from running)?
Thanks
First step would be to optimize that query, 20 seconds is way too long for most queries. Users won't generally tolerate that kind of poor performance.
If this is using Ajax, disable the
button that starts the query until
after the query is finished.
When the use makes the request, set a
flag in the user session, and then
start the query on a separate thread.
If they try to submit it again, check
the flag, and simply ignore the
request. When the query finishes,
reset the flag. While the query is
running, the browser can poll the
server waiting for the results.
I am not an expert, but you can store the time he last filed the query in his session. If the same user file another query with 20 secs, just ignore it.
It's not really a brute force way though.