This topic discusses how transactions interact with other VMware Tanzu GemFire features.
Designs that incorporate more complex features introduce further considerations:
For performance, transactions that operate on more than one partitioned region require that those partitioned regions colocate their entries. Colocate Data from Different Partitioned Regions describes how to colocate entries.
For performance, server-invoked region operations return references to region entries. Any assignment to that reference changes the entry within the region. This subverts the system’s ability to maintain consistency and the callback chain for handlers such as cache writers and cache loaders.
Changing an entry using a reference from within a transaction executing on a server has the same consistency issues, but is even worse, as the change will not be seen as part of the transactional state.
There are two ways to work with a reference: make a copy, or configure the system to return copies instead of references. There is a performance penalty to having the system return copies. Both ways are detailed in Copy on Read Behavior.
When more than one region participates in a transaction, and there is at least one partitioned and at least one replicated region, the code must do its first operation on the partitioned region to avoid a TransactionDataNotColocatedException
. Write the transaction to do its first operation on a partitioned region, even if the operation will be spurious.
Tanzu GemFire’s implementation of atomic transactions prohibits regions with persistence from participating in transactions. The invocation of a persistent region operation within a transaction throws an UnsupportedOperationException
with an associated message of
Operations on persist-backup regions are not allowed because this thread
has an active transaction
An application that wishes to allow operations on a persistent region during a transaction can set this system property:
-Dgemfire.ALLOW_PERSISTENT_TRANSACTIONS=true
Setting this system property eliminates the exception. It does not change the fact that atomicity is not enforced for disk writes that occur with the commit of a transaction. A server crash during the commit may succeed in some, but not all of the disk writes.
Queries and query results reflect region state, and not any state or changes that occur within a transaction. Likewise, the contents and updates to an index do not intersect with any changes made within a transaction. Therefore, do not mix transactions with queries or indexed regions.
LRU eviction and transactions work well together. Any eviction operation on a region entry that is operated on from within a transaction is deferred until the transaction is committed. Further, because any entry touched by the transaction has had its LRU clock reset, eviction is not likely to choose those entries as victims immediately after the commit.
A transaction deactivates expiration on any region entries affected by the transaction.
For best performance, non-transactional operations do not acquire the exclusive locks used to check for conflicts in a transaction. A transaction operating on the same data as a non-transactional actor is unable to detect the conflict caused by a non-transactional operation.
If using transactions, an application should adopt the policy of designating certain regions or sets of entries exclusively for transactional puts, updates, and deletions, so transactional entries will not be modified by non-transactional operations.
If other, non-transactional sources update the keys the transaction is modifying, the changes may intermingle with the transaction’s changes. The other sources can include distributions from remote members, loading activities, and other direct cache modification calls from the same member. When this happens, after your commit finishes, the cache state may not be what you expected.
An application requiring a strict, but slower isolation model, such that dirty reads of transitional states are not allowed, should set a property and encapsulate read operations within the transaction. Configure this strict isolation model with the property:
-Dgemfire.detectReadConflicts=true
This property causes read operations to succeed only when they read a consistent pre- or post-transactional state. If not consistent, Tanzu GemFire throws a CommitConflictException
.