![JAR search and dependency download from the Maven repository](/logo.png)
org.multiverse.api.IsolationLevel Maven / Gradle / Ivy
Show all versions of multiverse-core Show documentation
package org.multiverse.api;
/**
* With the IsolationLevel you have a way to provide declarative control to guarantee isolation between transactions.
* The transaction is free to provide a higher isolation than the one specified.
*
* The dirty read isn't added since atm we already have an extremely cheap read using the atomicWeakGet on the
* refs. Using the atomicWeakGet you have extremely cheap access to committed data.
*
* The following isolation anomalies have been identified:
*
* - Dirty Read
* - Unrepeatable Read
* - Inconsistent Read
* - Write Skew
*
*
* Dirty Read
*
* The DirtyRead isolation anomaly is that one transaction could observe uncommitted changes made by another transaction.
* The biggest problem with this anomaly is that eventually the updating transaction could abort and the reading transaction
* sees changes that never made it into the system.
*
*
Currently the Dirty Read anomaly is not possible in Multiverse since writes to main memory are deferred until commit
* and once the first write to main memory is executed, the following writes are guaranteed to succeed.
*
*
Unrepeatable Read
*
* The Unrepeatable Read isolation anomaly is that a transaction could see changes made by other transactions. So at one
* moment it could see value X and a moment later it could see Y. This could lead to all kinds of erratic behavior like
* transaction that can get stuck in an infinitive loop.
*
*
Such a transaction is called a zombie transaction and can cause serious damage since they are consuming resources
* (like cpu) and are holding on to various resources (like Locks). So the unrepeatable read should be used with care.
*
*
Inconsistent Read
*
* With the inconsistent read it is possible that a value is read depending on a previous read value that has been updated
* by another transaction. E.g. there are 100 refs all initialized with the same value and there is an updating transaction
* that increments all value's by one, and there is a reading transaction that reads all refs, then it should see the same
* values for all values.
*
*
Writeskew
*
* With the writeskew problem it is possible that 2 transactions commit....
*
*
Example 1: there are 1 person that has 2 bank accounts and the invariant is that the sum of both bank accounts is
* always equal or larger than zero. If user has has 50 euro on both accounts (so the sum is 100) and there are 2 transactions
* that both subtract 100 euro from the bank accounts, and the first sees account1=50 and account2=50, the subtraction is allowed
* and subtracts it 100 from the first account, and the second transaction sees exactly the same and subtracts 100 from the second
* account, it could be possible that the person ends up with -50 on both accounts (so a sum of -100), clearly violating the
* contract that the the sum should never be smaller than 0.
*
*
Example 2:
*
*
Isolation Levels
*
* The following isolation levels are currently defined in Multiverse:
*
* - Read Committed
* - Repeatable Read
* - Snapshot
* - Serialized
*
* The read uncommitted is currently not defined since currently there is no need to do a dirty read, there will always be committed
* data available for reading (the write is deferred till commit, so you won't have to see transactions in progress).
*
*
*
*
*
*
* Implementation and isolation level upgrade
*
* An implementation of the {@link Txn} is free to upgrade the isolation level to a higher one if it doesn't support that specific isolation
* level. This is the same as Oracle is doing with the ReadUncommitted, which automatically is upgraded to a ReadCommitted or the RepeatableRead which is
* automatically upgraded to Snapshot (Oracle calls this the Serialized isolation level).
*
*
Isolation: pessimistic or optimistic
*
* Isolation through locking
*
*
*
*
* @author Peter Veentjer.
* @see TxnFactoryBuilder#setIsolationLevel(IsolationLevel)
*/
public enum IsolationLevel {
/**
* With the RepeatableRead isolation level you will always see committed data and next to that once a read
* is done, this read is going to be repeatable (so you will see the same value every time).
*/
RepeatableRead(false, true, true),
/**
* The default isolation level that allows for the writeskew problem but not for dirty or unrepeatable
* or inconsistent reads.
*
* This is the 'serialized' isolation level provided by MVCC databases like Oracle/Postgresql
* (although Postgresql 9 is going to provide a truly serialized isolation level) and MySQL with the InnoDb.
* All data read. contains committed data and all data will be consistent.
*
* A transaction that is readonly, gets the same isolation behavior as the Serializable isolation level
* since the writeskew problem can't occur (nothing can be written).
*/
Snapshot(false, false, true),
/**
* Provides truly serialized transaction at the cost of reduced performance and concurrency. This is the highest
* isolation level where no isolation anomalies are allowed to happen. So the writeSkew problem is not allowed to
* happen.
*/
Serializable(false, false, false);
private final boolean allowWriteSkew;
private final boolean allowUnrepeatableRead;
private final boolean allowInconsistentRead;
IsolationLevel(boolean allowUnrepeatableRead, boolean allowInconsistentRead, boolean allowWriteSkew) {
this.allowUnrepeatableRead = allowUnrepeatableRead;
this.allowInconsistentRead = allowInconsistentRead;
this.allowWriteSkew = allowWriteSkew;
}
/**
* Checks if the writeskew problem is allowed to happen.
*
* @return true if the writeSkew is allowed to happen.
*/
public final boolean doesAllowWriteSkew() {
return allowWriteSkew;
}
/**
* Checks if the dirty read is allowed to happen (so reading data that has not been committed).
*
* @return true if the dirty read is allowed to happen.
*/
public boolean doesAllowUnrepeatableRead() {
return allowUnrepeatableRead;
}
/**
* Checks if the inconsistent read is allowed to happen.
*
* @return true if the inconsistent read is allowed to happen.
*/
public boolean doesAllowInconsistentRead() {
return allowInconsistentRead;
}
@Override
public String toString() {
return "IsolationLevel." + name();
}
}