I have a situation like in a Java application like , "if an there is an entry in a table and simultaneously there is a delete request also how will we handle such a scenario".
Could anybody suggest me on how to deal with issues like these which could work on small as well as large applications?
I think the question is how the UI/UX should be handled when such scenario occurs. Besides the concurrency issue described in question, there can be other scenarios like user 1 opens edit person page, in the mean time, user2 deletes that record from another login. What should happen when user1 tries to save the record?
You should probably return an error message to the user stating the details of the error(record deleted, updated by someone else etc.).
Your question is very wide and such is the aswer.
I will narrow the problem a bit, by assuming you are using spring(boot). If so then It is very easy to answer.
Use the #Transactional annotation above the methods that contain the logic to either save or delete. And include required libraries ofc.
With the methods annontated in such a way, the spring(boot) application will guarantee that both operations will occur in the order that is required to maintain a consistent database.
If an error occurs, you can handle this in higher levels of your application or just show an error to the user.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have a java swing application that connects to MySQL database and performs transactions perfectly alright. There are one-up numbers as well that are generated for transactions. Data does get committed most of the times without any issue. But there have been instances where, in some of the cases, the previously committed data gets wiped off from the database altogether and the one up numbers also rollback. For example, if I have done invoices with one up invoice numbers from 1 to 200, the next morning when I check the sales report, it shows transactions with ID from 1 to 100 only. The rest of the data go missing. But since I have printed invoice copies of all invoices from 1 to 200, I am certain that the transactions have indeed taken place. Is there anything in MySQL that I need to watch out for?? Will upgrading to MySQL version 8 help? I feared there is some kind of malware in the machine, so I have even tightened the antivirus but that hasn't helped. I have set a very strong MySQL DB password as well. Nothing seems to have helped prevent this from happening.
For example, if I have done invoices with one up invoice numbers from 1 to 200, the next morning when I check the sales report, it shows transactions with ID from 1 to 100 only. The rest of the data go missing. But since I have printed invoice copies of all invoices from 1 to 200, I am certain that the transactions have indeed taken place.
What you have stated doesn't prove that the transaction committed. One possibility is that the invoice was printed during the transaction; i.e. before you committed it.
We can't eliminate this possibility without examining your code. And there could be any number of other possibilities like that.
Is there anything in MySQL that I need to watch out for?
I am aware of nothing in MySQL that would cause spontaneous roll-back of transactions that have been committed.
Will upgrading to MySQL version 8 help?
It is highly unlikely that it will help. More to the point, you won't really know for sure that it has made any difference ... if you don't know the real cause.
Here's some possible explanations. There are probably others.
Bugs in your code; e.g. see above.
Some scheduled task (that you might have forgotten about or not know about) has bugs in it.
Something is restoring an older version of your database.
A previous employee / developer left a "time bomb" in your code.
A hacker (or a previous employee or a current employee) has access to the system and is "messing with you".
Malware / viruses (though it is unlikely that generic malware would cause this kind of behavior). And note that "tightening" your AV may not help if you have already been infected.
Some strange MySQL bug that I've never heard of.
I would suggest things like:
checking all accounts for the system are secure, and close any that shouldn't be there anymore,
checking the system access logs, etcetera for signs of unauthorized access or access at unexpected times
use MySQL Enterprise Audit - https://dev.mysql.com/doc/refman/8.0/en/audit-log.html
implement something that (for example) takes periodic snapshots of certain tables that you can then use for later analysis.
Our application is based on Java, JPA and an Oracle database. If a database operation fails, I get a SQLException or one of it's derivates.
In my case I'd like to distinguish, whether a SQLIntegrityConstraintViolationException has been caused by a problem with a unique or a foreign key constraint.
The log shows the error code ORA-00001 for the unique constraint violation, however, I was looking for a list of the other codes in order to reacte to the right ones.
I'm aware that these codes are vendor specific and SO has an easy to find answer for MySQL. I would need the same for Oracle.
Not surprisingly, there's a list in the OracleDOcumentation:
http://docs.oracle.com/cd/B28359_01/server.111/b28278/toc.htm
but digging in from the top it's also not so easy to find. Since MySql-Answers were so much easier to find, I hope, this Q&A serves to provide an equally quick path to this information.
Unfortunately, one cant't easily search inside the list because it has been spread across multiple pages without much indication on which range contains what kinds of errors.
However, I managed to find the codes for my specific problem: UQ violation is ORA-00001, where as the foreign key errors are found under ORA-02290 (missing parent) and ORA-02291 (attempted delete with dependant children existing).
This problem might be even broader. Error handling is vendor specific and JDBC does not handle vendor specific stuff.
For example JBOSS has class in it called: ExceptionSorter see OracleExceptionSorter. This class lists all the critical error codes describing the situation that the error is on "connection level". So the connection has to be closed and (after some time) a new one has to be created.
Then there are errors on "transaction level". Obviously it is a deadlock "ORA-0060" and then some crazy error returned by concurrent "MERGE" statements. These error can be usually solved by rollback a re-trying the whole transaction.
The rest of the errors are usually related to data integrity, and these can not be re-tried.
I'm not aware of any exception sorted implementation, which covers all classes of error. Maybe it is not even possible to implement, as it can depend on application needs.
I have a problem with duplicate records arriving in our database via a Java web service, and I think it's to do with Oracle processing threads.
Using an iPhone app we built, users add bird observations to a new site they visit on holiday. They create three records at "New Site A" (for example). The iPhone packages each of these three records into separate JSON strings containing the same date and location details.
On Upload, the web service iterates through each JSON string.
Iteration/Observation 1. It checks the database to see if the site exists, and if not, creates a new site and adds the observation into a hanging table.
Iteration/Obs 2. The site should now exists in the database, but it isn't found by the database site check in Iteration 1, and a second new site is created.
Iteration/Obs 3. The check for existing site NOW WORKS, and the third observation is attached to one of the existing sites. So the web service and database code does work.
The web service commits at the end of each iteration.
Is the reason for the second iteration not finding the new site in the database due to delays in Oracle commit after it's been called by the Java, so that it's already started processing iteration 2 by the time iteration 1 is truly complete, OR is it possible that Oracle is running each iteration on a separate thread?
One solution we thought about was to use Thread.sleep(1000) in the web service, but I'd rather not penalize the iPhone users.
Thanks for any help you can provide.
Iain
Sounds like a race condition to me. Probably your observation 1 and 2 are arriving very close to each other, so that 1 is still processing when 2 arrives. Oracle is ACID-compliant, meaning your transaction for observation 2 cannot see the changes made in transaction one, unless this one was completed before transaction two started.
If you need a check-then-create functionality, you'd best synchronize this at a single point in your back end.
Also, add a constraint in your DB to avoid the duplication at all costs.
It's not an Oracle problem; Thread.sleep would be a poor solution, especially since you don't know root cause.
Your description is confusing. Are the three JSON strings sent in one HTTP request? Does the order matter, or does processing any of them first set up the new location for the ones that follow?
What's a "hanging table"?
Is this a parent-child relation between location and observation? So the unit of work is to INSERT a new location into the parent table followed by three observations in the child table that refer back to the parent?
I think it's a problem with your queries and how they're written. I can promise you that Oracle is fast enough for this trivial problem. If it can handle NASDAQ transaction rates, it can handle your site.
I'd write your DAO for Observation this way:
public interface ObservationDao {
void saveOrUpdate(Observation observation);
}
Keep all the logic inside the DAO. Test it outside the servlet and put it aside. Once you have it working you can concentrate on the web app.
In troubleshooting operations issues, I'm finding it difficult at times to diagnose a problem without more details. I see from timestamps that a merchant record changed on a particular date, for example, and the processing of transactions on the prior day is called into question. Logging what changed could help quickly rule out possibilities.
Are there any utilities out there that do that sort of comparison automatically? I'd like it to be able to do something like:
String logDelta=SomeLibrary.describeChanges(bean1, bean2);
I'd be hoping for a one-liner with something like:
"lastName{'Onassis','Kennedy Onassis'}, favoriteNumber{16,50}"
This is called an audit trail or an audit log and it's generally done in the database using triggers or stored procedures to make a copy of the row in the database being changed with the name of the user and the timestamp. It's very common to do this for compliance reasons. I haven't seen any packages that manage it for you because it's usually very tightly coupled to the database design.. you don't necessarily want a copy of every single row or every field, and it can become very expensive to do this in a highly transactional environment.
Try googling 'audit trail'
I've been researching how to fix this issue for sometime but can't seem to find a proper solution.
Here's the issue:
I have a Java EE application where many users can login, they are presented with an item list, and they can select and edit any one of those.
All users see the same item list.
As mentioned, they can edit an item but I'd like to restrict the editing function to one user. That is, many users can edit different items simultaneously but only one user can edit a particular item.
When one user is editing an item, an message should appear to any other user trying to edit that item.
I have implemented this by setting a flag on the item, inUse, to true and then check for that. When the user is done editing the item, either by clicking save or cancel, the flag is set to false.
Problem with this approach is to account for cases when the user leaves his browser open or the browser is closed.
I tried setting a session timeout but can't seem to make that work because when the session times out, I don't have access to that item. I only have access to the httprequest session id.
Perhaps this is the wrong approach since it seems it's an issues that many applications would have and a less hackie solution should exist.
I looked into using threads and synchronized methods but don't know how that would work because once the user enters into the edit item screen, the method exits and releases the lock.
I found this solution Only one user allowed to edit content at a time but not sure if that's the way to go in Java.
Is there a more elegant/java solution? If so can you point me in the right direction please? How would you implement this?
Thanks!
The solution:
Although originally I thought optimistic locking was the way to go, I quickly realized that it wouldn't really work for my environment. I decided to go with a combination of pessimistic locking (http://www.agiledata.org/essays/concurrencyControl.html#PessimisticLocking) and timeouts.
When an item is accessed, I set an inUse field to true and the object's last accessed field to the current time.
Everytime when somebody tries to edit the object, I check the inUse field and the lastAccessed field + 5 mins. So basically, I give 5 mins to edit the user.
Do it like they do in a database, where a timestamp is used. The timestamp is kept with the record and when a person submits his edit, the edit does not go through unless the timestamp is the same (meaning 'no edits have occurred since I read this record'). Then when the edit does go through, a new timestamp is created.
First of all, in your persistence layer, you really should be doing optimistic locking, using a version/timestamp field.
At a UI level, to handle your use case I would do resource leasing:
Add two fields to your table:
LAST_LEASE_TIME: Time of the last lease
LAST_LEASE_USER: User that leased the record for the last time.
When a user tries to edit your record, first check that the record is not leased, or that the lease has expired (that is, the lease is not older that the specified lease time) or that the user is the one that was granted the lease.
From your web browser, periodically renew the lease, for example with an AJAX call.
When the user ends editing the record, explicitly expire the lease.
By doing leasing, you solve the "closed browser" problem: after the lease period expires without any lease renovation, the algorithm automatically "releases" the resource.
Sounds like you could use : Session Beans Quote:
In general, you should use a session bean if the following circumstances hold:
At any given time, only one client has access to the bean instance.
The state of the bean is not persistent, existing only for a short period of time (perhaps a few hours).
Martin Fowler describes 4 patterns for such a problem:
Online Optimistic Locking
Online Pessimistic Locking
Offline Optimistic Locking
Offline Pessimistic Locking
You should decide which one to use according to your problem.
JPA, JDO and Hibernate provide 1 and 2 out of the box.
Hibernate can handle 3 too, (I'm not sure about JPA and JDO).
None handle 4 out of the box and you shall implement it yourself.