| --- |
| title: Design Considerations |
| --- |
| |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <a id="transaction-considerations"></a> |
| |
| Designs that incorporate more complex features introduce further |
| considerations. |
| This section discusses how transactions interact with other |
| <%=vars.product_name%> features. |
| |
| - **[Colocate Partitioned Regions](#colocate-PRs)** |
| - **[Region Operations Return References](#copy-on-read-transactions)** |
| - **[First Operation with Mixed Region Types](#first-op-with-mixed-types)** |
| - **[Allowing Transactions to Work on Persistent Regions](#transactions-persistence)** |
| - **[Mixing Transactions with Queries and Indexes](#transactions-queries)** |
| - **[Mixing Transactions with Eviction](#transactions-eviction)** |
| - **[Mixing Transactions with Expiration](#transactions-expiration)** |
| - **[Changing the Handling of Dirty Reads](#transactions-dirty-reads)** |
| |
| ## <a id="colocate-PRs" class="no-quick-link"></a>Colocate Partitioned Regions |
| |
| 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](../partitioned_regions/colocating_partitioned_region_data.html) describes how to colocate |
| entries. |
| |
| ## <a id="copy-on-read-transactions" class="no-quick-link"></a>Region Operations Return References |
| |
| 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](../../basic_config/data_entries_custom_classes/copy_on_read.html). |
| |
| ## <a id="first-op-with-mixed-types" class="no-quick-link"></a>First Operation with Mixed Region Types |
| |
| 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. |
| |
| ## <a id="transactions-persistence" class="no-quick-link"></a> Allowing Transactions to Work on Persistent Regions |
| |
| <%=vars.product_name%>'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 |
| |
| ``` pre |
| 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. |
| |
| ## <a id="transactions-queries" class="no-quick-link"></a>Mixing Transactions with Queries and Indexes |
| |
| 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. |
| |
| ## <a id="transactions-eviction" class="no-quick-link"></a>Mixing Transactions with Eviction |
| |
| 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 id="transactions-expiration" class="no-quick-link"></a>Mixing Transactions with Expiration |
| |
| A transaction disables expiration on any region entries affected |
| by the transaction. |
| |
| ## <a id="transactions-dirty-reads" class="no-quick-link"></a>Changing the Handling of Dirty Reads |
| |
| 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, |
| <%=vars.product_name%> throws a `CommitConflictException`. |
| |
| |