I am having trouble running my code. Every time I enter user information to sign up a user i get the the error:
java.sql.SQLException: database is locked
The error is most likely a result of incomplete operations you have started and not finished elsewhere against the database, such as transactions you haven't committed. You should close all resources. Something somewhere didn't get closed properly, causing the lock to stay on.
Result of your query() method - the result set - is never closed.
It is helpful to tell which database are you using, since they have different ways of handling locks.
Also, you may wish to add simple debug points, like "System.out.println" to each of your database operations. This helps you to see the flow of database statements which end up with a lock.
Once you have an exception, you shall keep the exception call stack. This helps to identify on which SQL operation did you get the lock - and helps focusing on the real problem.
(May I suggest considering MVC or a light DDD to isolate gui and db code to keep your code clean, and avoiding doing any database operation from the event handling thread since that will eventually introduce lockups on your gui, once you get as big as spotify. :))
Related
Due to the slowness of the application, we made some of our long running queries asynchronous. Problem is these are part of a single transaction but in case if these queries/routines fail I need to roll back everything. How to achieve this? This application is legacy application using JDBC oracle and java 8. Also like to know if there is any support for this in Springboot, jpa application.
Thanks in advance.
Don't try to interact with the same DB connection from multiple threads at once. JDBC's connection system isn't specced to let you do this.
A transaction belongs to a single connection. You can't smear it out over multiples.
The obvious way to ensure that 'it is all rolled back' is to have a single long-lived transaction (but see later).
Combine these 3 facets and you end up with: Do all work in the async block. At least, all work that either needs to all happen, or none of it happens (i.e. the one transaction).
Any other basic approach wouldn't work or wouldn't be useful; there's no point freezing the main thread to wait for the async task (just do the async task on the spot; moving code to another thread doesn't magically make it go any faster. On the contrary, in fact).
However, transactions that aren't just long lived, but make a ton of changes to a DB is its own problem, but we now we're getting into the performance characteristics of your specific batch of queries and your particular DB engine, version, indices, and data. Kinda hard to answer with specifics, what with all those unknowns.
There are ways to design your DB to deal with this (mostly involving a table representing a calculation, and having a row indicate whether the calculation is complete or not. As long as you aren't done, dont set it to 'completed', and all your queries should ignore non-complete results. Upon bootup, delete (and with it, let that cascade) any non-complete results: Those must be half-baked work done right before your server crashed, and now you've restarted it). It's probably not the right answer here, just making sure you're aware that such options also exist.
As a general rule of thumb, countering a problem of "Our code has been observed to run too slowly" with "lets make it all async" doesn't work. async makes code harder to read, way harder to debug, and doesn't make stuff go faster. All you can really do with async is soothe the user by playing them some elevator music or slightly more pragmatic: A progress bar or whatnot, whilst they wait. And that's actually generally easier by spawning off the bits that tell the user what's happening into a separate thread, instead of asyncing the work itself. That, and make your algorithm better and/or fix your DB index definitions. You can search the web for that too; run EXPLAIN variants of your queries to make the DB tell you whether it is using any table sweeps (that's where it goes through the entire dataset before it can answer a query. You want to avoid those).
If you need help with either of those parts (show the user what is going on, instead of freezing the webpage or freezing the GUI / how to optimize a DB query), search the web for this information, there are tons of tutorials. Make sure to include the frontend tech; java can be used for swing apps, javafx, android, and there are at last count like a 100 web frameworks.
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";);
I just have a problem relative to concurrency whose logic flow is when a client (called Oracle Forms) will submit a request (called concurrent program ) and call a plsql procedure, this procedure eventually will call a java static method.
What I find is that when I submit two request in the same time or in a very short interval(like 1 second), some concurrency problem will be noticed.
The java method is the start point of doing something that search from the database suggest that which records should be inserted into database.
The problem is that, they will result in duplicated result since when I query, both request find it fine to insert new records.
I tried add synchronized in the static java method, but this does not solve this problem, why?
What I do is:
public static synchronized void execute
Please note that the insert will be called in plsql, which means I do a not sufficient synchronize if only synchronize the java method. But when I look into the log, it shows the two request run in the same second, which I do not think it is normal! since query database and doing the suggestion is time consuming.
To make the java method really time consuming, I add a code call Thread.sleep(5000), and log for the time after this code and log the thread id.
Surprise to see that the Thread id is 1! And also, the time where they pass the sleep is in the same time. Why is that?
What can I do to solve the problem? Any lock on the java method or pl sql?
PS: I am now trying to use DMBS_LOCK, and which seems to be working but I still hope to know the reason why the java method is not synchronized.
I have no idea how the JVM inside the Oracle DB is implemented, but since (at least in some common configurations) every database connection gets its own server process, then if a separate JVM is embedded into each of those, a synchronized block won't do you much good. You'd need to use database locks.
Assuming that the calls to the Java static method are done within the same classloader, then synchronized is all you need.
Your logging may be faulty. How exactly are you logging?
Your statement about the database lookup being "time consuming" is not convincing. Databases tend to cache data, for example.
In a nutshell: if, by your definition, an "atomic operation" is a combination of lookup + insert, then you should "synchronize" over both. Acquiring a database lock seems like a reasonable way to go about it.
I am developing an program that uses transactions, for data integrity.
I have read about jdbc savepoints where one can rollback to a point where there was no error in the transaction.
But there is one situation, say the network fails, that makes the connection handling the transaction to be invalid.
Now i have managed to detect in my program whenever a network problem occurs, make appear a dialog that will block the ui for 2 minutes while trying to establish a connection to the db.
my question is, is there a way to save a transaction, not a savepoint, or re establish the connection where a network failure occured in during the transaction, so that if connection is re established, we can continue with the prevous queries?
why i want this is because my program will perform transactions over multiple modal dialogs before commit, say dialog A queries were successfull, when we go to dialog B before committing, if a network error occurs here we should be able to continue where we left off in dialog A.
Thanks in advance.
Suspending a database transaction during "user think-time" is bad news. A more appropriate strategy is to use "versioning".
This is done by adding a column to your record that increments with every update. When a user reviews the record to think about changes, the version is loaded. When the changes are applied, the version is compared to ensure it has not changed. If it has changed, you have a "soft deadlock", which can be addressed in a few ways:
Warn the user that another change has been made, and ask to confirm an overwrite
Present the user with a list of updates that occurred during their think-time, and if they want to overwrite them. This can be tricky because you should refresh the version number for the confirmation, recheck it if they choose to overwrite, and give them yet another warning/confirmation if something changed while they were deciding to overwrite. Your process should be designed to do this forever if necessary.
Prevent the update outright
If your main concern is data integrity and ODBC backend database is ACID-compliant, then you do not need to worry. Simply re-do the transaction after re-establishing the connection, and that will work just fine.
I'm currently working on a (rather large) pet project of mine , a Swing application that by it's very nature needs to be multi-threaded. Almost all user interactions might fetch data from some remote servers over the internet , since I neither control these servers nor the internet itself, long response times are thus inevitable. A Swing UI obviously cannot repaint itself while the EDT is busy so all remote server calls need to be executed by background thread(s).
My problem:
Data fetched by the background threads gets 'enriched' with data from a local (in-memory) database (remote server returns IDs/references to data in the local database). This data later eventually gets passed to the EDT where it becomes part of the view model. Some entities are not completely initialized at this point (lazy-fetching enabled) so the user might trigger lazy-fetching by e.g. scrolling in a JTable. Since the hibernate session is already closed this will trigger a LazyInitializationException. I can't know when lazy-fetching might be triggered by the user so creating a session on demand/attaching the detached object will not work here.
I 'solved' this problem by:
using a single (synchronized , since Session instances are not thread-safe) Session for the whole application
disabling lazy-fetching completely
While this works, the application's performance has suffered greatly (sometimes being close to unusable). The slowdown is mainly caused by the large number of objects that are now fetched by each query.
I'm currently thinking about changing the application's design to 'Session-per-thread' and migrating all entities fetched by non-EDT threads to the EDT thread's Session (similar to this posting on the Hibernate forums).
Side-note: Any problems related to database updates do not apply since all database entities are read-only (reference data).
Any other ideas on how to use Hibernate with lazy-loading in this scenario ?
Don't expose the Session itself in your data API. You can still do it lazily, just make sure that the hydration is being done from the 'data' thread each time. You could use a block (runnable or some kind of command class is probably the best Java can do for you here unfortunately) that's wrapped by code that performs the load async from the 'data' thread. When you're in UI code, (on the UI thread of course) field some kind of a 'data is ready' event that is posted by the data service. You can then get the data from the event use in the UI.
You could look have a look at Ebean ORM. It is session-less and lazy loading just works. This doesn't answer your question but really proposes an alternative.
I know Ebean has built in support for asynchronous query execution which may also be interesting for your scenario.
Maybe worth a look.
Rob.
There are two distinct problems, that should get resolved seperately:
Handling of Hibernate Sessions in Swing Applications. Let me recommend my own article, regarding this problem: http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-applications/
The basic idea is to have a session for every frame, excluding modal frames which use the session of the spawning frame. It is not easy but it works. Meaning, you won't get any LLEs anymore.
How to get your GUI thread separated from the back end.
I recommend to keep the hibernate objects strictly on the back end thread they originate from. Only give wrapper objects to the ETD. If these wrapper objects are asked for a value, they create a request which gets passed to the backend thread, which eventually will return the value.
I'd envision three kinds of wrapper Implementations:
Async: requests the value, and gets notified when the value is available. It would return immediately with some dummy value. On notification it will fire a PropertyChange event i.O. to inform the GUI about the 'changed' value (changed from unknown to a real value).
Sync: requests the value and waits for it to be available.
Timed: a mixture between the two, waiting for a short time (0.01) seconds, before returning. This would avoid plenty change events, compared to the async version.
As a basis for these wrappers a recommend the ValueModel of the JGoodies Binding library: http://www.jgoodies.com/downloads/libraries.html
Obviously You need to take care that any action is only performed on actually loaded values, but since you don't plan on doing updates this shouldn't be to much of an issue.
Let me end with a warning: I have thought about it a lot, but never actually tried it, so move with care.