When using mapped fields, you must also choose a concurrency control model. Concurrency control prevents overlapping updates from entity instances running in different threads or different servers, or from applications running outside of EAServer. There are two approaches for concurrency control:
In the Pessimistic concurrency control (PCC) model, data rows are locked when read, for the duration of the EAServer transaction. This method can introduce database deadlocks and usually reduces the scalability of the application.
In the Optimistic concurrency control (OCC) model, data rows are not locked when read. Timestamps are used for concurrency control; the timestamp can be a timestamp column in the database that is updated every time the row is modified, or it can be the row data itself. At the end of the transaction, the in-memory timestamp value is compared to the timestamp value in the database, and the transaction rolls back if the values do not match.
OCC allows greater scalability than PCC, however, when using OCC, client applications must be coded to retry rejected updates, or you must enable automatic transaction retry for the application components as described below.
When using OCC, each update statement contains SQL logic that determines if the last-read timestamp matches the stored value, and rolls back the transaction if the timestamp does not match. In other words, updates based on stale data are rejected. There are several options for using timestamps:
Use a timestamp column: each table contains a timestamp column, which can be a database timestamp type (if supported) or an integer column that is incremented for every update. This option provides good performance if your database and table schema can support it.
Use all-values comparison: on update, all row values are compared to the last-read values to detect update collisions. OCC with all-values comparison is the default concurrency control model. Performance with this option is worse than when using a single timestamp column, particularly if the table contains many columns or wide columns (such as Sybase text or image columns). Whenever possible, the use of a timestamp column is recommended in these cases.
Use a table-level timestamp: the timestamp is a single integer counter that is incremented for every update, insert, or delete in the main table. This option provides the best performance for CMP entity beans that are mapped to read-mostly (or read-only) tables when verified results are required to meet transaction isolation requirements. For best results, use table-level timestamps with a Sybase CMP wrapper driver to allow verification queries to be batched with other deferred operations. For more information, see “Using CMP JDBC wrapper drivers” in the EAServer Performance and Tuning Guide.
Enabling optimistic concurrency control
Configure the Timestamp field on the Persistence/General subtab. Table 27-1 describes the allowable values. For best performance when using tables with many columns or large column values (such as Sybase text or image columns), specify a timestamp column as described in Table 27-1.
If multiple tables are used and you specify a timestamp column, all tables must contain a column with the same name and datatype.
To configure |
Set the timestamp value to |
---|---|
A timestamp column |
The name of a single column in each table that serves as the timestamp to detect update collisions. If the component uses multiple tables, each must contain a timestamp column with this name. The column type can be:
|
A table level timestamp |
A table and column name, in the form A timestamp table can be shared among multiple components even when only one column is present in the timestamp table. In other words, a single timestamp value can be shared by multiple tables. This helps further improve performance for a group of read-mostly tables. However, any insert, delete, or update on any of the tables results in all cache entries being discarded. When using a timestamp table, database triggers are required to increment the timestamp for each update, delete, or insert to tables that are mapped to the component or components that require the timestamp. You can set the component property com.sybase.jaguar.component.ts.triggers property so EAServer creates triggers, create triggers yourself, or add code to existing triggers. |
All values comparison |
Leave blank. |
Optionally enable auto-retry for the application components so that EAServer replays EJB CMP transactions that fail due to conflicting updates. Auto-retry must be configured for the component that initiates the transaction, which is typically a session bean in EJB applications. Auto-retry works only for intercomponent calls, not for direct invocations of entity beans from the Web tier or base clients. Configure auto-retry as follows:
In the properties of the components that initiate the transactions to be retried, use the Advanced tab to set the property com.sybase.jaguar.component.tx_retry. A value of true enables auto retry. A value of false disables auto-retry. If this property is not set, the value of the server property com.sybase.jaguar.server.tx_retry is used. If neither the component property or server property is set, the default is false.
In server properties, use the Advanced tab to set the property com.sybase.jaguar.server.tx_retry. The default of false disables auto-retry for all components for which auto-retry is not explicitly enabled. Specify true to enable auto-retry for components for which auto-retry is not explicitly set to false.
Auto-retry is not appropriate for all applications. For example, an end user may want to cancel a purchase if the item price has risen. If auto-retry is disabled, clients must be coded to retry or abort transactions that fail because of stale data. The exception thrown is CORBA::TRANSIENT (for EJB clients, this exception is the root cause of the java.rmi.RemoteException thrown by the EJB stub).
For EJB CMP entity beans, configure an effective transaction isolation level, as described in “Configuring CMP isolation level” in the EAServer Performance and Tuning Guide.
Verify that the Select With Lock option on the Persistence/General subtab in the Component Properties dialog box is disabled. On the Advanced tab, verify that com.sybase.jaguar.component.selectForUpdate is not set or set to false.
Enabling pessimistic concurrency control
Configure a locking mechanism. You can do one of the following:
Enable the Select With Lock option on the Persistence/General subtab. When using jagtool or XML configuration files, set com.sybase.jaguar.component.selectWithLock to true.
Enable the Select for Update option by setting the com.sybase.jaguar.component.selectForUpdate property to true on the Advanced tab in the Component Properties dialog box or by using jagtool or an XML configuration file. This setting requests an exclusive database lock be obtained at select time to avoid deadlocks during lock promotion. Also consider configuring the database table for row-level locking.
Configure the table-mapping select queries and add “holdlock” or the appropriate lock syntax for your database. See “Configuring table-mapping properties” for more information.
Make sure that OCC is disabled by setting the Timestamp field to “none” on the Persistence/General subtab in the Component Properties dialog box.
Copyright © 2005. Sybase Inc. All rights reserved. |