05 Transactions


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

05 Transactions

  1. 1. Transactions Managing concurrent data access
  2. 2. Transactions <ul><li>All operations inside a transaction either complete or fail: </li></ul>Transaction begin rollback commit Transaction Succeeded Transaction Failed Initial State
  3. 3. Hibernate transaction support <ul><li>Hibernate supports system transactions with </li></ul><ul><ul><li>JDBC transaction management if we use a connection pool directly </li></ul></ul><ul><ul><li>JTA transactions in Application Servers </li></ul></ul><ul><ul><li>any custom TransactionFactory and Transaction implementation </li></ul></ul><ul><li>The Hibernate Transaction API hides the underlying </li></ul><ul><li>strategy and keeps our persistence layer code portable. </li></ul>
  4. 4. The Hibernate Transaction API <ul><li>Use the Transaction API to control system/database transactions: </li></ul><ul><li>Committing the Transaction flushes the Session. </li></ul><ul><li>Do we need anything else? </li></ul><ul><li>Can we have several Transactions per Session? </li></ul>Session session = sessions.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); concludeAuction(); tx.commit(); } catch (Exception e) { if (tx != null) tx.rollback(); throw e; } finally session.close(); }
  5. 5. Session flushing and closing <ul><li>A flush synchronizes the Session state with the database </li></ul><ul><ul><li>Hibernate uses write-behind for SQL execution </li></ul></ul><ul><ul><li>Hibernate uses JDBC batch-updates </li></ul></ul><ul><li>A flush occurs </li></ul><ul><ul><li>when a Transaction is committed </li></ul></ul><ul><ul><li>before a query is executed (for correct query results) </li></ul></ul><ul><ul><li>when an application calls Session.flush() </li></ul></ul><ul><li>We can control this behavior by setting a FlushMode for a particular Session . This is useful for some rare cases with database triggers. </li></ul><ul><li>Always close the Session and don’t forget to </li></ul><ul><li>discard it if any exception occurs. </li></ul>
  6. 6. Session granularity I <ul><li>One Session and one database transaction per request/response: </li></ul><ul><li>Simple applications don't need anything else! </li></ul>S1 Request T1 Response
  7. 7. Long running application transactions <ul><li>A user needs time to think </li></ul><ul><ul><li>a logical application transaction might span several request/response </li></ul></ul><ul><ul><li>e.g. load data in a screen and submit the changes after 5 minutes </li></ul></ul><ul><li>We never hold transactions or even connections open across user think time! </li></ul><ul><li>So one application transactions might span several database transactions. </li></ul><ul><li>How can we guarantee consistency and isolation for </li></ul><ul><li>coarse-grained long running application transactions? </li></ul>
  8. 8. Application Transaction: An example <ul><li>Two system administrator edit the same user account and submit: </li></ul><ul><ul><li>Last commit wins: Both succeed, the second update overwrites the changes, no error message is shown. </li></ul></ul><ul><ul><li>First commit wins: The first succeeds and the second administrator gets an error message, he restarts the process with fresh data. </li></ul></ul><ul><ul><li>Merge conflicting changes: The first succeeds and the second administrator merges his changes manually. </li></ul></ul><ul><li>Hibernate can help: </li></ul><ul><ul><li>The first strategy is the default if we don't change anything </li></ul></ul><ul><ul><li>Hibernate uses managed versioning for optimistic locking to implement the second and third strategy. </li></ul></ul>
  9. 9. Session granularity II <ul><li>Application transactions with detached objects and many Sessions: </li></ul><ul><li>We load objects in a first Session and reattach with </li></ul><ul><li>saveOrUpdate() and/or lock() in a second Session. </li></ul><ul><li>The special saveOrUpdateCopy() method is useful if the </li></ul><ul><li>detached entities are already loaded in the second Session. </li></ul>S1 Request T1 Response S2 Request T2 Response Detached Instances Application Transaction
  10. 10. Session granularity III <ul><li>Implementing application transactions with long Sessions: </li></ul><ul><li>Atomicity is guaranteed if only Tx updates data and </li></ul><ul><li>any other T n only reads data! This is also true for </li></ul><ul><li>the detached instances concept, however, it is </li></ul><ul><li>usually more difficult to implement using long Sessions. </li></ul>S1 Request T1 Response Request Tx Response Disconnected from JDBC connection Application Transaction
  11. 11. Managed versioning <ul><li>A timestamp/version is incremented everytime the data is updated </li></ul><ul><ul><li>we have to add a new property to our persistent class </li></ul></ul><ul><ul><li>we have to map it with <version> or <timestamp> </li></ul></ul>public class Item { ... private int version; ... private void setVersion(int version) { this.version = version; } private int getVersion() { return version; } } <class name=&quot;Item&quot; table=&quot;ITEM&quot;> <id ..... <version name=&quot;version&quot; column=&quot;VERSION&quot;/> ... </class>
  12. 12. Managed versioning in action <ul><li>Hibernate will </li></ul><ul><ul><li>automatically set the value of the version/timestamp property </li></ul></ul><ul><ul><li>increment it automatically whenever an item is modified </li></ul></ul><ul><ul><li>throw an exception if the version has been increment meanwhile </li></ul></ul><ul><ul><li>use only a single UPDATE by default (checking the return value) </li></ul></ul><ul><li>If this update returns zero updated records, someone has increment this version of the record already and we have stale data! </li></ul>update ITEM set DESCRIPTION='New Description', SELLER=45, VERSION=3 where ID=123 and VERSION=2
  13. 13. Managed version without a version/timestamp property <ul><li>Optimistic concurrency can be used without extra columns: </li></ul><ul><ul><li>Hibernate will use the &quot;old&quot; object state to check all columns for modification when updating and throw an exception if anything changed. </li></ul></ul><ul><li>Only works for version checks in a </li></ul><ul><li>single Session, no detached objects! </li></ul><class name=&quot;Item&quot; table=&quot;ITEM&quot; optimistic-lock=&quot;all&quot; > <!-- we might also use &quot;dirty&quot; for only changed values --> <id ..... ... </class> update ITEM set DESCRIPTION='New Description', SELLER=45 where ID=123 and DESCRIPTION='Old Description' and SELLER=45
  14. 14. Transaction isolation I <ul><li>Concurrency problems: </li></ul><ul><ul><li>Lost update: tx1 write / tx2 write / tx2 rollback </li></ul></ul><ul><ul><li>Dirty read: tx1 write / tx2 read / tx1 rollback </li></ul></ul><ul><ul><li>Unrepeatable read: tx1 read / tx2 write / tx1 read </li></ul></ul><ul><ul><li>“ Second” lost update: tx1 read / tx2 read / tx1 write / tx2 write </li></ul></ul><ul><ul><li>Phantom read: tx1 read / tx2 insert / tx1 read </li></ul></ul><ul><li>ANSI isolation levels: </li></ul><ul><ul><li>Read uncommitted: no lost updates (write locks) </li></ul></ul><ul><ul><li>Read committed: no dirty reads (write locks, momentary read locks) </li></ul></ul><ul><ul><li>Repeatable read: no unrepeatable reads or “second” lost updates (write locks, read locks) </li></ul></ul><ul><ul><li>Serializable: no phantom reads (table-level locks) </li></ul></ul>Which isolation level should we use with Hibernate?
  15. 15. Transaction Isolation II <ul><li>Dirty reads are evil! </li></ul><ul><ul><li>We might read dirty values, and re-write them, after they have been rolled back </li></ul></ul><ul><ul><li>We could end up with dirty values in the second-level cache </li></ul></ul><ul><ul><li>If we use versioning, rollback of one transaction could cause failure of other concurrent transactions </li></ul></ul><ul><li>Phantom reads are not usually harmful </li></ul><ul><ul><li>And, in addition, serializable transaction isolation is very unscalable </li></ul></ul><ul><li>So, should we use repeatable read, or read committed? </li></ul><ul><ul><li>Versioning prevents the “second” lost updates problem </li></ul></ul><ul><ul><li>Use of the second-level cache violates repeatable read isolation </li></ul></ul><ul><ul><li>Unrepeatable reads are not usually harmful </li></ul></ul><ul><ul><li>We can acquire a read lock explicitly by requesting LockMode.UPGRADE on many databases </li></ul></ul><ul><li>So, on balance, read committed is the best choice for most systems (not coincidentally, this is the default for most databases) </li></ul>