Connection cache settings  CMP runtime monitoring

Chapter 4: EJB CMP Tuning

Entity instance and query caching

EAServer supports object and query caching for EJB entity beans and entity components that use automatic persistence. Caching can improve performance by minimizing the number of database select queries required for ejbLoad operations, finder method invocations, and ejbSelect method invocations. Most database applications are governed by the 80:20 rule: 80% of users access 20% of the data. Object caching increases performance and scalability by allowing faster access to the most recently used data.

Assuming that the database access is the principal bottleneck, the expected performance gain falls in these ranges, depending on the ratio of update to read-only transactions:

Besides the transaction mix, the actual performance gain depends on:

In summary, the best use case for caching is data that is static. If the data changes often, the overhead of updating caches can outweigh the performance benefits of caching. If the data is updated too frequently, soft locking or hard locking may yield better performance. Furthermore, the data consistency requirements dictate how cached data can be used. Decide how much consistency you require, then optimize within those constraints.

Cache synchronization can be enabled to minimize the occurrences of transaction rollback due to overlapping updates. EAServer supports cache synchronization between servers in a cluster and from the database to EAServer. In some cases, the overhead of synchronization may outweigh the benefits incurred.


Cache architecture

Object and query caching place an in-memory cache and a cache manager component in between component instances and the associated database. You can configure the object cache and cache manager used by each entity component. You can configure the query cache used by each finder and ejbSelect method. You can configure caches that are dedicated to a single component or query method or shared by multiple components and query methods.

For components, object caching is enabled if you have configured an isolation level that requires caching. You can further customize the caching parameters as described in “Configuring object caching”. Query caching must be configured for each finder and ejbSelect method, on the Persistence/Query Mapping subtab in the Component Properties dialog box. See “Enabling query caching”. Query caching is disabled by default.


Cache coherency and transaction consistency

When data is maintained in the object cache as well as the source database, you must take steps to ensure these transactional constraints are satisfied:

Read consistency If your application requires read consistency, choose an isolation level that requires it, such as read_committed_verify_updates or read_committed_with_cache_verify_updates. See “Configuring CMP isolation level”. When read consistency is required, caching should be used only when the data changes infrequently. Caching volatile data can make your application perform worse because the added overhead of retrying queries that roll back because the data changed.

Update consistency When using caching, transactional update consistency is ensured by:

Read consistency using timeouts and synchronization For applications that have a more lax requirement for read consistency, you can configure cache timeouts and synchronization to minimize the use of stale data. The cache timeout sets a time limit on how long cached data remains valid. Stale entries are refreshed from the source database before the data is used in the component. You can also configure your database to notify the cache manager of updates, inserts, and deletes. Doing so allows EAServer to refresh the cache contents after data is modified by another application. See “Enabling database change notification” for more information. The same notification technique is used for both object caching and query caching.

In addition, if the component is deployed in a cluster, you can configure inter-server synchronization, which uses the EAServer message service to replicate data changes between servers in the cluster. This ensures that all caches have the same data. To use this option, configure the Cache Synchronization property described in “Configuring object caching”.


Configuring object caching

For each entity component that uses automatic persistence, enable object caching on the Persistence/Object Cache subtab in the Component Properties dialog box. The settings are:

StepsCreating a named cache

If you want a cache to be shared by multiple components, finder methods or ejbSelect methods, you must create a named cache as follows:

  1. If the Repository/ObjectCache directory does not exist under your EAServer installation, create it.

  2. Create a text file in the Repository/ObjectCache directory named Cache.props, where Cache is the cache name used in component properties.

  3. Add lines as shown below to configure the cache properties. All properties are optional. If not set, the default values apply:

    com.sybase.jaguar.objectcache.size=size-value
    com.sybase.jaguar.objectcache.timeout=timeout-value
    com.sybase.jaguar.objectcache.sync=sync-method
    

    These values correspond to the component object caching properties, as described in the table below. Each cache property uses the same value syntax as the corresponding component property:

    Named cache property

    Component property

    com.sybase.jaguar.objectcache.size

    Cache Size. If not specified, the default is unlimited.

    com.sybase.jaguar.objectcache. timeout

    Cache Timeout. If not specified, the default is infinity.

    com.sybase.jaguar.objectcache.sync

    Cache Synchronization


Enabling query caching

Query caching allows EAServer to cache the values returned by finder and ejbSelect method queries. When caching is enabled for a query, the key values returned by each invocation are cached in memory, with the method input parameter values serving as the cache key. Together with entity object caching, query caching can reduce the number of unnecessary database reads.

To enable caching for a finder or ejbSelect query, append [cache] to the end of the Query Mapping property value that corresponds to the method. For example:

[default][cache]

Or, for a query mapped to an EJB-QL query:

ejbQuery:[cache]

You can specify optional parameters with this syntax:

[cache cache-params]

Where cache-params is a list of parameters listed in Table 4-5, with each parameter separated from the next by white space, for example:

[default][cache size=1M timeout=10]
Table 4-5: Query cache configuration parameters

Parameter

To indicate

name=name

The cache name. Specifying a named cache allows multiple queries to use one cache. The named cache must be created and configured as described for named object caches in “Configuring object caching”.

Only one of name or size may be specified.

size=size

The cache size. Only one of name or size may be specified. The value syntax is:

  • nM or nm to specify a size in Megabytes, for example: 1M

  • nK or nk to specify a size in kilobytes, for example: 512k

  • n to specify a size in bytes, for example: 1048576

timeout=seconds

The cache timeout in seconds. A value of 0 indicates infinity.

verify

Specifies that finder results must be verified at the end of the transaction. Restrictions apply—see “Verifying cached finder method results” for more information.

ignore insert

If database change notification is enabled, inserts do not invalidate the cache.

ignore delete

If database change notification is enabled, deletes do not invalidate the cache.

ignore update

If database change notification is enabled, updates do not invalidate the cache.

Verifying cached finder method results To obtain verified finder method semantics, include the keyword verify in the cache settings for the finder query. For example, use [cache verify] in place of [cache]. For components using object caching, this setting specifies that any finder method data used from cache should be verified at commit time with an appropriate database query. The verification query runs with an isolation level that is equivalent to higher than the component isolation level. Query cache verification requires the use of a table-level timestamp, and all tables referenced in the SQL query must use the same table timestamp as the entity bean for which the finder method is defined.


Configuring transaction local cache settings

EAServer uses the transaction local cache to minimize the number of database reads required when finder methods are called in a transaction. For example, if a finder method returns 100 rows, the worst case requires 101 queries to retrieve the data for each row. The transaction local cache helps achieve the ideal of selecting all required data at the beginning of the transaction.

The transaction local cache is enabled automatically if finder queries return enough data to populate the cache. In other words, the finder query returns all rows in the table. The default query properties do this. If you have modified them, verify that they return all rows. For more information, see “Specifying finder- and ejbSelect-method queries” in Chapter 27, “Creating Entity Components,” in the EAServer Programmer’s Guide.

You can set the component property com.sybase.jaguar.component.tlc.sort to specify whether EAServer sorts entries before calling ejbStore. Setting this property to true helps to avoid deadlock when separate transactions concurrently update multiple instances of the same component. The default of false may provide better performance by eliminating the sorting step. You cannot enable sorting unless the primary key class implements the java.lang.Comparable interface. Most java.lang utility classes implement this interface, such as String, Integer and so forth.


Enabling database change notification

This feature allows the use of database triggers to notify EAServer's entity object cache of changes to the underlying table rows. The notification mechanism works as follows:

  1. Database triggers call a stored procedure sp_publish to publish a message for each SQL insert, update or delete.

  2. sp_publish “publishes” the messages by placing them in a table cms_notify.

  3. A cluster-wide singleton service, CtsComponents/DatabaseNotify, pulls notification messages from the cms_notify table using stored procedure sp_notify. These messages are then published to the EAServer message service. The expected latency for message delivery (from trigger to cache entry removal) is approximately one second at most.

  4. The storage component (when using CtsComponents/JdbcStorage) listens for messages on selected topics, parses the messages for key fields, and notifies the Object Cache to remove the relevant entries.

StepsEnabling database change notification

  1. Install the required stored procedures in the target database(s). See “Sample script for database stored procedures”.

  2. In the EAServer Manager properties for your server, use the Advanced tab to configure the property com.sybase.jaguar.server.services to include the Message Service and Database Notify components, for example:

    CtsComponents/MessageService,CtsComponents/DatabaseNotify
    

    If you have never run the message service in your installation, configure the message service as described in Chapter 8, “Setting up the Message Service,” in the EAServer System Administration Guide. Database change notification requires a working message service.

  3. Optionally add an entry to MessageServiceConfig.props to specify the name(s) of connection caches for databases which need to be monitored for notification messages. These connection caches must have type JDBC, for example:

    dn.caches=SybaseCache,OracleCache
    

    By default, the cache referenced by the cms.cache property will be used.

  4. Optionally add an entry to MessageServiceConfig.props to specify the JDBC callable statement (or prepared statement) to be used to pull change notification messages from the database, for example:

    sp_notify={call my_own_notify_proc ?,?}
    

    By default, the callable statement is:

    {call sp_notify ?,?}
    
  5. For each entity component that is to be configured for database notification, enable the Create Database Triggers option on the Persistence/General subtab in the Component Properties dialog box. This option requests automatic creation of triggers.

  6. Optionally change the message service topic names associated with database tables. The default topic name is the unqualified table name. You must change the topic name if multiple databases contain tables with the same name. To change the topic name associated with a table, set the table mapping property for the table’s notify operation, as described on “Configuring table-mapping properties” in the EAServer Programmer’s Guide.


Sample script for database stored procedures

For Oracle databases, a sample script is provided in the the file DatabaseNotify_Oracle.sql in the Repository/Component/CtsComponents subdirectory of your EAServer installation. The sample script below is for Sybase Adaptive Server Enterprise. Modifications are required for use on other databases:

use master
go

if not exists (select name from sysdatabases where name = "notifydb")
  begin
    create database notifydb
    exec sp_dboption notifydb, "trunc log on chkpt", "true"
  end
go

use notifydb
go

checkpoint
go

if not exists (select 1 from sysobjects where name="cms_notify" and type="U")
  begin
    create table cms_notify
    (
      id numeric(16,0) identity primary key,
      type char(1) not null,
      name varchar(100) not null,
      message varchar(255) not null,
      options varchar(255) not null
    )
  end
go

if not exists (select 1 from sysusers where name="guest")
  exec sp_adduser guest
go

use sybsystemprocs
go

if exists (select 1 from sysobjects where name="sp_notify" and type="P")
  drop proc sp_notify
go

create proc sp_notify
  (@from numeric(16,0),
  @last numeric(16,0))
as
  if @from <= @last
    delete from notifydb..cms_notify where id >= @from and id <= @last
  declare @loop int
  select @loop = 1
  while @loop <= 60
    begin
      declare @rows int
      select @rows = count(*) from notifydb..cms_notify
      if @rows > 0
        begin
          set rowcount 100
          select id, type, name, message, options
            from notifydb..cms_notify
            order by id
          return
        end
      waitfor delay "00:00:01"
      select @loop = @loop + 1
    end
go

sp_procxmode sp_notify, anymode
go

grant execute on sp_notify to public
go

if exists (select 1 from sysobjects where name="sp_publish" and type="P")
  drop proc sp_publish
go

create proc sp_publish
  (@topic varchar(255),
  @message varchar(255),
  @options varchar(255))
as
  insert into notifydb..cms_notify (type, name, message, options)
    values ("T", @topic, @message, @options)
go

sp_procxmode sp_publish, anymode
go

grant execute on sp_publish to public
go

if exists (select 1 from sysobjects where name="sp_send" and type="P")
  drop proc sp_send
go

create proc sp_send
  (@topic varchar(255),
  @message varchar(255),
  @options varchar(255))
as
  insert into notifydb..cms_notify (type, name, message, options)
    values ("Q", @topic, @message, @options)
go

sp_procxmode sp_send, anymode
go

grant execute on sp_send to public
go


Customizing the implementation

The storage component responds to any suitably formatted messages that are published to the configured topic names for each mapped table. You can provide you own implementation of the stored procedures or the notification component.

To publish a change message, the Message Service 'text' property should be “insert”, “delete” or “update”, each key column should have a corresponding property (unless multiple rows were affected in which case key columns should be omitted). If using the Java Message Service (JMS) to publish the messages, use a TextMessage and use header properties for the key column values.





Copyright © 2005. Sybase Inc. All rights reserved. CMP runtime monitoring