Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Commitment ordering wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
Clusterpoint wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Database model wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Object-relational impedance mismatch wikipedia , lookup
Transaction Commit Options EJB™ Entity beans in the container of Borland® Enterprise Server by Jonathan Weedon, Architect: Borland® VisiBroker® and Borland® AppServer,™ and Krishnan Subramanian, Enterprise Consultant Introduction This paper provides an overview of the transaction commit options defined in the Enterprise JavaBeans™ (EJB™) specification and how the EJB container in Borland® Enterprise Server, AppServer Edition handles those options. The various transaction commit options defined in the EJB specification are applicable to entity beans only. This paper enumerates the behavior and performance of entity beans running within the EJB container of Borland Enterprise Server when using each of the transaction commit options. Entity beans reviewed Borland Software Corporation Entity beans provide an object view of data. The data is usually June 2002 stored in a relational database, although it is also possible for an entity bean to provide an object view of an existing (legacy) application. To maintain data integrity, entity beans usually are accessed in the scope of a transaction. Contents The EJB container of the Borland Enterprise Server manages Introduction 1 Instance life cycle 2 Transaction commit options 4 Conclusion 9 the synchronization among concurrent invocations from multiple client threads; the bean provider need not be concerned with this fact. To support concurrency, the EJB container creates as many instances of entity beans as there are simultaneous transactions; this is one of the strengths of EJB container implementation (for both EJB™ 1.1 and EJB™ 2.0) by Borland. Some vendors serialize access to a single entity bean instance, limiting scalability. Borland® Enterprise Server EJB container Instance life cycle The EJB 1.1 and EJB 2.0 specifications define three states for an entity bean instance: Single entity bean instance Clients ¾ Does not exist ¾ Pooled state ¾ Ready state Figure 1: Serializing access to an entity bean. In the following sections, we discuss each of these states and As the preceding figure shows, some vendors attempt to solve how the container moves entity beans among the various states. the problem of synchronizing concurrent client access to entity beans by serializing access to a single entity bean instance. Does not exist However, this solution is not scalable since a single entity bean The “does not exist” state is not particularly interesting, as this is instance cannot efficiently service requests when the number of the state an entity bean is in before it is instantiated. This state is clients increases. Note also that this solution is imperfect when analogous to nothingness. the EJB container is clustered. Pooled state The “pooled” state is where an entity bean’s life starts, when the EJB container of Borland Enterprise Server EJB container instantiates the entity bean. After creating an instance, the container then invokes the setEntityContext(EntityContext) method to pass the created instance a reference to the EntityContext interface. The pooled state is where an entity bean instance is not associated with a primary key. Clients DOES NOT EXIST Figure 2: How the EJB container of Borland Enterprise Server handles simultaneous client requests. ejbFind…(args) ejbSelect…(args)* ejbHome…(args)* * EJB 2.0 only As the above figure shows, the EJB container of Borland Enterprise Server creates as many instances of entity beans as there are simultaneous transactions. That is, these instances run Step 1: newInstance() Step 2: setEntityContext(ec) POOLED in parallel, servicing client requests more efficiently. Figure 3: Pooled state. 2 Borland® Enterprise Server Beans in this state can be used to execute methods in the home POOLED interface. Note that a call to methods in the home interface will result in the instance remaining in the pooled state. The property ejbActivate() ejb.maxBeansInPool controls the number of bean instances in this state, with a default setting of 1000. When the container CACHED WITHOUT STATE starts up (or is restarted), there are no instances in the pooled state. That is, the pool is filled lazily in the Borland Enterprise Server. The number of entity bean instances in this state Figure 4: Cached without state. increases as required, depending on access by various clients. Ready state Transactional state An entity bean is in the “ready” state when the instance is The “transactional” state is where entity bean instances actually associated with a specific object identity. In other words, the execute business methods. Beans in this state are always given entity bean instance is associated with a primary key. Let’s associated with a transaction and typically return to the cached extend this aspect of the EJB specification with our own or pooled state at the end of the transaction. visualization for the sake of clarity. POOLED ejbPassivate() ready state: ¾ Cached state ¾ Transactional state ejbActivate() Assume there are two sub-classifications of bean instances in the CACHED WITHOUT STATE Cached state The cached state is where an entity bean instance is associated ejbLoad() TRANSACTIONAL ejbStore() Figure 5: Transactional state. with a primary key. Depending on the transaction commit option (discussed in the next section), the bean instance might As seen in the figure above, the entity bean instance in the also be associated with state (state means the persisted fields “Cached without state” knows only about its primary key and other than the primary key). The size of this cache is governed not the values of its persisted fields. The value of these persisted by the ejb.maxBeansInCache property, with a default setting fields needs to be synchronized with those in the database; this is of 1000. As in the pooled state, the number of entity bean accomplished via a call to the ejbLoad() method. Once the instances in the cached state is filled lazily as new primary keys ejbLoad() is performed, the entity bean will have all the are encountered. If the application uses a small table or a few persisted fields in sync with those in the database (for that rows from a given table, often far fewer than 1000 beans are transaction) and can then execute business methods. typically in use. For performance reasons, you may want to increase the size of this cache since it increases the likelihood of a cache hit (i.e., the given item could be retrieved from the cache). Caveat: Too many entity bean instances in memory may start to impact garbage collection, although this depends on the configuration of the Java™ Virtual Machine (JVM™) and hardware. 3 Borland® Enterprise Server ¾ POOLED ejbPassivate(): This disassociates the bean from its primary key, i.e., the bean instance returns to the ejbPassivate() ejbRemove() ejbActivate() pooled state. POOLED CACHED WITHOUT STATE ejbLoad() TRANSACTIONAL Step 1: ejbActivate() Step 2: ejbLoad() ejbStore() business methods ejbSelect…(args)* * EJB 2.0 only Step 4: ejbStore() Step 5: ejbPassivate() TRANSACTIONAL Figure 6: Transactional state transitions. Step 3: business method(s) Transaction commit options Figure 7: Option C—bean states. There are three transaction commit options defined by the EJB 1.1 and EJB 2.0 specifications. These are commit options A, B, Option B and C. We start with option C, as it is the simplest behavior. Option B is the default behavior of Borland Enterprise Server. Here, bean instances are kept in the cache: the bean instances are Option C associated with a primary key, but the state of an entity bean’s In option C, the cache is not used, that is, the property persisted fields are not synchronized with the values in the ejb.maxBeansInCache is ignored. Entity bean instances in database. When a client invokes a business method, the EJB this pool wait for something to do. If a call on the home container checks its cache to see whether a corresponding bean interface occurs, the entity bean executes against an instance instance (identified by its primary key) exists. If so, then that from this pool—which is in fact the behavior for all commit cached instance is taken out and used. The ejbLoad() is options. If a business method is invoked by a client, the invoked on this cached instance to synchronize its state following sequence of calls is made: ¾ (persisted fields) with those in the database. ejbActivate(): This associates the bean instance with a primary key. ¾ If the cache does not contain an instance associated with that ejbLoad(): This associates the bean instance with the primary key (either because the bean associated with that state in the database i.e., the persisted fields in the primary key has not been accessed previously or because some entity bean are synchronized with those in the database. other concurrent transaction has already taken the bean instance Following the above two calls, the business methods are out of the cache for its own use), then a bean instance is executed in the scope of that transaction. When the transaction transitioned out of the pooled state. In this case, the ends (i.e., the transaction commits), the following sequence of ejbActivate() is called to first associate the bean instance calls are made: ¾ with a primary key, then followed by a call to ejbLoad() to ejbStore(): This updates the database with the synchronize the state of the entity bean with the state in the changed values (if any) of the entity bean instance’s database. persisted fields. 4 Borland® Enterprise Server As indicated by the figure above, once the entity bean in the EJB container in Borland Enterprise Server transaction ready state executes the business method(s), the business method container calls the ejbStore() and sends the bean back to the PK=2 PK=5 Client cache. It is possible that the bean instance enters the pooled state after ejbStore() is called by calling ejbPassivate(): PK=8 this would happen if there already existed an entity in the cache Cached without state Pooled state for the given primary key. Figure 8: Option B—client invokes business method Option A In the preceding figure, assume that the cache of the EJB Option A provides optimized data access in cases where the EJB container holds three instances of an entity bean, each with its container has exclusive access to the database or where the own primary key (the entity bean instances only know their underlying data is either read only, or insert only. In other words, primary keys). Assume that there are a number of bean instances this option provides optimized data access in cases where in the pooled state; these instances are not associated with any existing rows in the database are not modified (though new ones primary key. could be inserted over time). The following sequences of events occur in the EJB container of In this case, the container uses a cache to hold the beans Borland Enterprise Server when a client invokes a business associated with a primary key. However, when Option A is used, method on an Option B entity bean: the entity beans are also associated with the state in the database. In other words, the entity bean instance not only holds the Does the entity bean referenced by the client exist in the cache? Yes, so get it out of the cache primary key field but also the values for all its persisted fields. The handling of Option A by the Borland Enterprise Server is very similar to the handling of entity beans using Option B. As No, so get any instance out of the pool with Option B, when a client invokes a business method, the EJB container first looks in the cache. If the entity bean instance CACHED WITHOUT STATE ejbLoad() ejbActivate() matching that primary key identity is found, the instance is taken out from the cache and used. It should be noted that if the cache POOLED does contain the required entity bean instance, then a call to the ejbPassivate() ejbLoad() can be avoided because the state of the bean is known to be consistent with the state from the last committed ejbStore() transaction. TRANSACTIONAL If the entity bean instance cannot be found in the cache, then the EJB container gets an instance from the pool and calls the execute business method(s) ejbLoad() to load the state from the database. Figure 9: Option B—handling request internally by the container. 5 Borland® Enterprise Server EJB container in Borland Enterprise Server Combining the facts that (a) Option A can suppress reads from the database (when that instance is present business method in the cache), and (b) the difference detection engine in PK=2 PK=5 Client the Borland implementation for CMP eliminates writes to the database (i.e., eliminates updates in the PK=8 Cached with state ejbStore() method) when no fields were modified, Pooled state demonstrates how our product provides entity bean support with no database access. In other words, a Figure 10: Option A—client invokes business method. pure middle-tier data cache! In the figure above, the cache contains three entity bean instances. These instances are associated with their primary key and with their state in the database. The pooled state contains Putting Option A beans back into the cache can be a bit tricky. entity bean instances that are not associated with any particular The Borland Enterprise Server uses a “first out, last in” primary key. The following sequences of events occur in the EJB algorithm—the first transaction that wants to use the bean container of Borland Enterprise Server when a client invokes a instance gets it from the cache. If a subsequent transaction(s) business method on an Option A entity bean: requests the same bean instance from the cache, we get a cache miss because the first transaction has already removed the bean Does the entity bean referenced by the client exist in the cache? Yes, so get it out of the cache instance from the cache. The cache miss implies that a bean instance has to be retrieved from the pool, then is followed by a call to ejbActivate() (to associate the instance with its No, so get any instance out of the pool primary key) and more importantly an ejbLoad(). That is, only the first transaction needing a particular bean can avoid an ejbLoad(). Concurrent transactions must get that bean from TRANSACTIONAL the database. POOLED Subsequently, the last transaction to complete successfully puts execute business method(s) the bean back in the cache. The implementation of Transaction Step 1: ejbActivate() Step 2: ejbLoad() Commit Option A by Borland provides the benefits of exclusive database access without the need to serialize entity bean access. Figure 11: Option A—handling request internally by the container. Serializing entity bean access implies that a single entity bean instance (in the ready state) services client requests in a serial manner. As mentioned in the beginning of this paper, this is not a scalable option. The following figure shows how the EJB container handles Option A entity beans accessed by concurrent transactions, labeled T1 and T2. The contents of the cache and the state of the entity bean are shown. Also illustrated is the way the last transaction to complete successfully puts the state associated with that entity bean instance back in the cache. 6 Borland® Enterprise Server T2 Cache bean state (in cache) get bean: 2 PK = 2 PK = 2 State = x T1 get bean: 2 ¾ Pooled ¾ Cached (may be with or without state, i.e., with state when Option A is used and without state when Option B is used) ¾ Transactional state In the following section, we discuss an interesting feature of modify state (x) to y commit transaction Does not exist empty not found, get from DB modify state (x) to z ¾ entity bean support that limits the number of entity bean instances in a transaction. PK = 2 PK = 2 State = y The ejb.maxBeansInPools and the ejb.maxBeansInCache properties control the pooled state and cached state, as mentioned above. The flag commit transaction PK = 2 PK = 2 State = z ejb.maxBeansInTransactions governs the number of bean instances possible in the transactional state. Typically, you would use this flag when you run a batch-style operation, such as if you were running through a large number of entity beans in a single transaction. For reasons of performance and isolation, you might want to run such batch-style operations in a single Figure 12: Option A—writing back to the cache from multiple transaction. Until now, we have seen cases where beans were transactions. returned to the cache or pool only upon transaction completion. The most common concern when running batch transactions The EJB 1.1 and 2.0 specifications actually suggest that that access a large number of entity beans is the resource usage Option A can only be used by serializing access to a in terms of memory increasing substantially. single entity bean instance. The fact that the Borland Enterprise Server, AppServer Edition provides The property ejb.maxBeansInTransactions controls the concurrent access to Option A beans (i.e. without the number of entity bean instances in the transactional state that are need for serializing access) correctly is cool! actually allocated to active transactions. The default size is 500, which is half the default size of the bean instances in the So far we have discussed only the settings in the EJB container pool/cache. So if the default sizes of the pool/cache were of the AppServer Edition to limit the number of bean instances changed, then the ejb.maxBeansInTransactions value in the pooled state or cached state. As we have discussed, the should probably be adjusted accordingly. EJB specification mentions the three states possible for an entity bean. The last state, the ready state, is split into two: cached state The way this property works is as follows: when a transaction and transactional state. So, in effect, there are four states accesses an entity bean, the entity bean instance is usually possible from our perspective: allocated to that given transaction. However, before the entity bean instance is allocated to that transaction, a check is made to see whether the number of entity bean instances in the transactional state exceeds the 7 Borland® Enterprise Server ejb.maxBeansInTransactions value. If so, then other For example, your session façade could initiate a transaction and beans in the current transaction are moved to the cache/pool by call an entity bean’s finder method that returned 100,000 rows. calling ejbStore() or ejbPassivate(), depending on the The session bean would then iterate through the finder commit option selected. In effect, the ejbStore() or collection, get the data from the entity bean, put these in some ejbPassivate() is not called at the end of a transaction but kind of a data structure, and return them to the client. Instead of rather when the number of entity bean instances exceeds the instantiating 100,000 objects (as many vendors do) the EJB limit set by the ejb.maxBeansInTransactions property. container instantiates only 500 objects (or whatever the size of the ejb.maxBeansInTransactions is set to be) and caches As the following figure shows, the elements that are light in a subset of the total rows (the subset has a default of 1000 color represent the number of beans in the cached state (the instances associated with the primary key, not the state). default limit is 1000). The elements within the smaller window, Instances are moved from the transaction state to the cached in a darker shade, represent the number of bean instances in the state, based on the Least Recently Used (LRU) algorithm. transactional state. The number of bean instances in the transactional state (the size of the smaller window) is governed Large-scale performance tests have shown that this by the ejb.maxBeansInTransactions property. In effect, implementation provides a good space/time tradeoff. The the EJB container dynamically “slides” the window of active strategy is extremely effective at keeping batch-style operations beans—as well as the window of cached beans—across the total running in a controlled amount of memory without impacting items in the data set. the performance of other types of transactions that do not "window" size governed by ejb.maxBeansInCache value "window" size governed by ejb.maxBeansInTransactions value In the CMP 1.1 engineof Borland Enterprise Server, we read all the results from the JDBC® ResultSet at one time. That is, if there were 100,000 records, we would read all 100,000 records from the ResultSet immediately, but only instantiate as many entity bean instances as there are set by the ejb.maxBeansInPool property. In the 5.x version of Borland Enterprise Server, which supports the EJB 2.0 specification, we lazy-load from the ResultSet Bean instances in cached state. Bean instances in transactional state Total rows (e.g. result of a finder method) exceed their transactional limits. also. That is, we do not scroll through the ResultSet returned by a SQL query when the finder executes. Rather, we scroll through the ResultSet as and when the caller requests more items. Figure 13: Use of ejb.maxBeansInTransactions property. 8 Borland® Enterprise Server Conclusion So, what should you do to optimize your application? The first Benchmarking clients typically access entities at random, in question is to determine whether your EJB container can use which case Option C might be preferred. And, of course, if you Option A. The answer would be based on whether it is possible have batch operations, you might want to consider the impact of to have exclusive access to the database or whether certain tables ejb.maxBeansInTrasanctions property. (or beans) are either read only or insert only. The Java™ ECperf™ benchmarking exercise conducted on the The next consideration is to determine which kinds of memory AppServer Edition has demonstrated that the default entity bean constraints you might have in your deployment environment. If configuration in the EJB container of Borland Enterprise Server your deployment environment provides only a small amount of is quite effective. Borland used the default configuration for all memory, you might want to reduce the size of the cache and entity beans in the ECperf test and found excellent results. We pool, likewise reducing the number of beans in transactions. did try changing a number of variables, including trying Option Option C will consume less memory than Option B due to the C instead of Option B (Option A is disallowed by ECperf run fact there is only a pool and no cache. Note that caches are rules), and varying the pool/cache sizes. effective only if there is a high likelihood of a cache hit (i.e., an item can be found in the cache). So, if your application exhibits In all cases, we found that such changes either hurt performance locality of reference as do most real world applications, then or had no measurable impact. So, unless there are significant Option B is preferable to Option C. memory constraints or unless Option A can be used, it is recommended that the default configuration be used as a starting point for performance optimization. Made in Borland® Copyright © 2002 Borland Software Corporation. All rights reserved. All Borland brand and product names are trademarks or registered trademarks of Borland Software Corporation in the United States and other countries. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All other marks are the property of their respective owners. Corporate Headquarters: 100 Enterprise Way, Scotts Valley, CA 95066-3249 • 831-431-1000 • www.borland.com • Offices in: Australia, Brazil, Canada, China, Czech Republic, France, Germany, Hong Kong, Hungary, India, Ireland, Italy, Japan, Korea, the Netherlands, New Zealand, Russia, Singapore, Spain, Sweden, Taiwan, the United Kingdom, and the United States. • 12691 100 Enterprise Way Scotts Valley, CA 95066-3249 www.borland.com | 831-431-1000 9