Grid cache transaction. Cache transactions have a default 2PC (two-phase-commit) behavior and
can be plugged into ongoing
JTA transaction by properly implementing
org.gridgain.grid.cache.jta.GridCacheTmLookupinterface. Cache transactions can also be started explicitly directly from
GridCacheProjection API
via any of the
'GridCacheProjection.txStart(..)' methods.
Cache transactions support the following isolation levels:
-
GridCacheTxIsolation#READ_COMMITTED isolation level means that always a committed value
will be provided for read operations. With this isolation level values are always read
from cache global memory or persistent store every time a value is accessed. In other words,
if the same key is accessed more than once within the same transaction, it may have different
value every time since global cache memory may be updated concurrently by other threads.
-
GridCacheTxIsolation#REPEATABLE_READ isolation level means that if a value was read once
within transaction, then all consecutive reads will provide the same in-transaction value. With
this isolation level accessed values are stored within in-transaction memory, so consecutive access
to the same key within the same transaction will always return the value that was previously read or
updated within this transaction. If concurrency is
GridCacheTxConcurrency#PESSIMISTIC, then a lock
on the key will be acquired prior to accessing the value.
-
GridCacheTxIsolation#SERIALIZABLE isolation level means that all transactions occur in a completely
isolated fashion, as if all transactions in the system had executed serially, one after the other.
Read access with this level happens the same way as with
GridCacheTxIsolation#REPEATABLE_READ level.
However, in
GridCacheTxConcurrency#OPTIMISTIC mode, if some transactions cannot be serially isolated
from each other, then one winner will be picked and the other transactions in conflict will result in
GridCacheTxOptimisticException being thrown.
Cache transactions support the following concurrency models:
-
GridCacheTxConcurrency#OPTIMISTIC - in this mode all cache operations are not distributed to other
nodes until
#commit() or
#commitAsync() are called. In this mode one
'PREPARE'message will be sent to participating cache nodes to start acquiring per-transaction locks, and once
all nodes reply
'OK' (i.e.
Phase 1 completes successfully), a one-way'
'COMMIT'message is sent without waiting for reply. If it is necessary to know whenever remote nodes have committed
as well, synchronous commit or synchronous rollback should be enabled via
GridCacheConfiguration#setWriteSynchronizationModeor by setting proper flags on cache projection, such as
GridCacheFlag#SYNC_COMMIT.
Note that in this mode, optimistic failures are only possible in conjunction with
GridCacheTxIsolation#SERIALIZABLE isolation level. In all other cases, optimistic
transactions will never fail optimistically and will always be identically ordered on all participating
grid nodes.
-
GridCacheTxConcurrency#PESSIMISTIC - in this mode a lock is acquired on all cache operations
with exception of read operations in
GridCacheTxIsolation#READ_COMMITTED mode. All optional filters
passed into cache operations will be evaluated after successful lock acquisition. Whenever
#commit() or
#commitAsync() is called, a single one-way
'COMMIT' message
is sent to participating cache nodes without waiting for reply. Note that there is no reason for
distributed 'PREPARE' step, as all locks have been already acquired. Just like with optimistic mode,
it is possible to configure synchronous commit or rollback and wait till transaction commits on
all participating remote nodes.
Cache Atomicity Mode
In addition to standard
GridCacheAtomicityMode#TRANSACTIONAL behavior, GridGain also supports
a lighter
GridCacheAtomicityMode#ATOMIC mode as well. In this mode distributed transactions
and distributed locking are not supported. Disabling transactions and locking allows to achieve much higher
performance and throughput ratios. It is recommended that
GridCacheAtomicityMode#ATOMIC mode
is used whenever full
ACID-compliant transactions are not needed.
Usage
You can use cache transactions as follows:
GridCache<String, Integer> cache = GridGain.grid().cache();
try (GridCacheTx tx = cache.txStart()) {
// Perform transactional operations.
Integer v1 = cache.get("k1");
// Check if v1 satisfies some condition before doing a put.
if (v1 != null && v1 > 0)
cache.putx("k1", 2);
cache.removex("k2");
// Commit the transaction.
tx.commit();
}