Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

05 Transactions


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

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>