StaleObjectStateException on high frequency updates

一世执手 提交于 2019-12-05 21:27:15

Are you very, very sure that you've set the TX to serializable? Because that should never happen on a serializable transaction.

If two TX read and modify the same row in a serializable transaction, then oracle throws an ORA-08177.

Please check that hibernate is actually setting the TX as serializable.

Edit

You can do what Jonas suggested or you can also check it from you application by getting the underlying connection and invoking Connection.getIsolationLevel(). For example

Connection c = session.connection()
int level = c.getIsolationLevel()

Edit 2

Ok, since you confirmed that the isolation level on the Connection is SERIALILIZABLE, could you check:

  • That the tables are using the innoDB engine.
  • As Jonas suggested, run SELECT @@tx_isolation; from your code while it is in the transaction. It should return SERIALIZABLE. This is to check that the Connection is actually propagating the isolation level. It's a bit paranoid, but what to do...
  • Check that your code only opens one transaction, and runs everything in that TX. I just tested the SERIALIZABLE isolation level manually and it works as expected (it blocks any TX trying to read the same row).
  • Last resort: check that the isolation level SERIALIZABLE works on your MySQL installation.

NOTE: As I mentioned before, MySQL will block any queries trying to read from the same row. That means that if you have some "common tables" such as country, company, user, etc. that many TXs read concurrently, it might make your app run almost sequencially rather than parallelly.

It seems like you have configured Hibernate to use optimistic concurrency control. That means that your User table has a version field that Hibernate increments on every row update.

Most likely your transaction starts at the beginning of the HTTP request and ends a the end of the HTTP response. This means that the process of editing a user consists of two transactions: one transaction to populate the web form and one transaction to save the changes.

In that case, changing the isolation level of the database will not do any good. Most likely all you will get is worse performance and scalability.

It is not a bad thing to have StaleObjectExceptions. It reflects the real world - people do actually work on the same thing once in a while and conflicts may occur. The question is, when a conflict has been detected, how do you resolve it in a manner that is satisfying to the end users? Can it be resolved without the assistance of the user?

Possible strategies could be to

  • overwrite the previous user's changes (often not what you want - hence the need for concurrency control),

  • show an error message asking the user to refresh and perform his changes again,

  • automatically merge the changes without overwriting the previous user's changes (sometimes possible)

  • inform the user about the staleness of his data and offer him a way to manually merge his changes

It all depends on the context.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!