[Building Sakai] Spring / Hibernate transactions - way too many

Noah Botimer botimer at umich.edu
Wed Sep 28 15:59:18 PDT 2011


Hello sakai-dev,

A pretty detailed observation/question here. First, the question, and then some background...

Has something changed? I seem to recall there being some automatic connection borrowing and transaction creation per request such that DAOs, etc., would just join that outermost transaction. Or am I mistaken, and we have been in a transaction-per-method model for all of recorded history?



Background:

We have a couple of beans to support Spring / Hibernate / transactions across tools: org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager and org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory. These are defined in the kernel, in db-components.xml.

Then tools that use Hibernate (generally?) have proxy beans defined for their DAOs/managers/services. These use org.springframework.transaction.interceptor.TransactionProxyFactoryBean, which allows for transaction management defined within the XML (usually components.xml, see below for an example from OSP).

The general idea of the common case (PROPAGATION_REQUIRED on all methods) is that the DAO methods will join an existing transaction or create one. This is supposed to allow for multiple methods to be called on the DAO and even some cross-service calls (say, to SiteService) within a single transaction.


The assumption:

A generally correct and useful behavior is transaction-per-request, with auto-commit / auto-rollback at the end of the request. Special needs can be managed manually.


The observation:

We are getting tons of transactions spawned when using these proxies. Generally every method call is finding no existing transaction and creating a very short-lived one (method duration only).  Note that this transaction is at the proxy boundary -- it can call its own or other proxies' methods and they will not nest new transactions down the call stack indefinitely. But also note that these transactions are also happening for simple getters: stuff that's expected to be fast and repeatable with negligible cost.


Depending on whether this is changed behavior (not sure as of when yet, maybe as old as 2.6 or older), we may have a lot of code spawning lots of extraneous transactions and bogging down needlessly. It could be the case that the shortcut was "good enough", where a few transactions are fine, and individually problematic cases should create wrapping transactions, but I want to be sure before embarking on anything of that severity. For reference, I'm working on SAK-20715, where request times of 8-minutes-plus have been recorded, most of which is spent in no-op transaction management. I'm also wondering about large-data cases in Hibernate-based tools like Gradebook and Samigo.

Any thoughts are welcome.

Thanks,
-Noah



Example proxy for HibernateMatrixManagerImpl (matrixManagerTarget), from OSP:

   <bean id="matrixManager"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
      singleton="true">
      <property name="transactionManager">
        <ref bean="org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager"/>
      </property>
      <property name="target">
         <ref bean="matrixManagerTarget"/>
      </property>
      <property name="transactionAttributes">
         <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
         </props>
      </property>
   </bean>




More information about the sakai-dev mailing list