liveBook · Manning

Repeatable read isolation level

As explained in Java Persistence with Spring Data and Hibernate epub

Repeatable read is a transaction isolation level under which repeated reads of the same data return a consistent value within a transaction, preventing unrepeatable reads while generally allowing phantom reads.

Repeatable read is a transaction isolation level for keeping a row's value stable across repeated reads within one transaction. It prevents an unrepeatable read: reading a value, then reading a different value after another transaction updates and commits it. It also prevents dirty reads and lost updates in the ANSI isolation-level comparison, but it does not prevent phantom reads. A repeated query can therefore return additional or fewer rows after another transaction inserts or deletes data. section 11.2.1

Table 11.1 ANSI isolation levels and the problems that they address (view table figure)

Isolation level

Phantom read

Unrepeatable read

Dirty read

Lost update

READ_UNCOMMITTED

–

–

–

+

READ_COMMITTED

–

–

+

+

REPEATABLE_READ

–

+

+

+

SERIALIZABLE

+

+

+

+

The isolation-level table compares which concurrency problems are prevented at each level: repeatable read rules out unrepeatable reads, while serializable also rules out phantom reads. section 11.2.1

Choose the level with the transaction's required guarantees in mind. Higher isolation has performance and scalability costs. A JPA pessimistic lock is a separate way to protect selected data: PESSIMISTIC_READ guarantees repeatable reads, while PESSIMISTIC_WRITE additionally requires serialized access without phantom reads. Hibernate's locking SQL depends on the database dialect, and the lock lasts only for the database transaction. section 11.2.1 section 11.2.3

Lock rows used in a calculation

A transaction totals item prices across categories by querying each category with setLockMode(LockModeType.PESSIMISTIC_READ) and a lock-timeout hint. Hibernate adds database-specific locking SQL: PostgreSQL can use FOR SHARE, whereas H2 uses FOR UPDATE for its pessimistic modes. If a required lock cannot be obtained, the operation throws an exception. section 11.2.3

Do not mistake a repeatable managed-entity result for transaction-level repeatable read. Without an active transaction, Hibernate can return an already-loaded entity from the persistence context, preserving its in-memory value, while a scalar query reads the database value in auto-commit mode. Database isolation also matters when refreshing entities: MySQL's stated default is REPEATABLE_READ, so an example that must see another transaction's committed changes configures the JDBC connection for READ_COMMITTED. section 11.3.1 section 13.1.3

How Java Persistence with Spring Data and Hibernate epub covers it

How deep it goes
Compares prevented anomalies, costs, and related JPA locking behavior, without specifying a database's internal isolation algorithm.
Examples
Uses an isolation-level comparison, a locked item-price calculation, and a MySQL JDBC setting for refresh visibility.
What it assumes
Assumes basic familiarity with transactions and database queries while defining the concurrency anomalies used to compare isolation levels.
What you can do after
Operate/configure it to preserve repeated row reads and adjust isolation when refresh must see another transaction's changes.
How it connects
Connects unrepeatable reads and phantom reads to pessimistic locking, persistence contexts, and entity refresh.

Also explained in

Compare how 2 books explain repeatable read isolation level →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Java Persistence with Spring Data and Hibernate epub. The section links point to the parts of the book it draws on.