2011-02-28 13 views
3

JPA-1.0、Hibernate、MySQL 5.0.84(innoDBテーブル)、Postgres 8.1.11(クライアントごとに異なるデータベース)を使用して同時トランザクションに問題があります。私はJPAトランザクションの仕様を読んでいるので、設定に関して何か不足しているかどうか分かりません。私が持っている問題によれば、 トランザクションアノテーションの特定の分離レベルを指定する必要があります。これは私がやったことですが、トランザクションをまとめてオフにするだけなので、永続化/更新はできません。JPA並行トランザクション

私のやっていることは、Webサーバ(私の場合はtomcat)へのhttp投稿を開始し、httpリクエストが入ってくると複数のDBトランザクションを生成しようとします。 各トランザクションは1つの挿入と2つの更新。この問題は、前回のインサートに基づく最終更新時に発生するようです。 だから、私がレコードAを挿入し、その後、レコードA

への外部キーであるレコードBは、以下を更新し、私は単一のHTTPリクエストを行う際に取得するログです:


org.springframework.orm.jpa.JpaTransactionManager:365 - Creating new transaction with name [biz.cytrus.overlord.v2.core.ExecutionLogAPI.create]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' 
org.springframework.orm.jpa.JpaTransactionManager:323 - Opened new EntityManager [[email protected]] for JPA transaction 
org.springframework.orm.jpa.JpaTransactionManager:355 - Exposing JPA transaction as JDBC transaction [org.springframewo[email protected]9f5742] 
org.springframework.orm.jpa.JpaTransactionManager:752 - Initiating transaction commit 
org.springframework.orm.jpa.JpaTransactionManager:462 - Committing JPA transaction on EntityManager [[email protected]] 
org.springframework.orm.jpa.JpaTransactionManager:548 - Closing JPA EntityManager [[email protected]] after transaction 
org.springframework.orm.jpa.EntityManagerFactoryUtils:329 - Closing JPA EntityManager 

次があります私は同時に複数のHTTPリクエストを行う際に取得するログ:


org.hibernate.util.JDBCExceptionReporter:357 - SQL Error: 1213, SQLState: 40001 
org.hibernate.util.JDBCExceptionReporter:454 - Deadlock found when trying to get lock; try restarting transaction 
org.hibernate.event.def.AbstractFlushingEventListener:532 - Could not synchronize database state with session 
org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update 
     at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:105) 
     at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) 
     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266) 
     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168) 
     at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) 
     at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) 
     at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027) 
     at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365) 
     at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137) 
     at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54) 
     at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467) 
     at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) 
     at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) 
     at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:375) 
     at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
     at $Proxy66.create(Unknown Source) 
     at biz.cytrus.overlord.v2.web.action.task.LogAction.createLogEntry(LogAction.java:84) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:592) 
     at net.sourceforge.stripes.controller.DispatcherHelper$6.intercept(DispatcherHelper.java:442) 
     at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:158) 
     at net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor.intercept(BeforeAfterMethodInterceptor.java:113) 
     at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:155) 
     at net.sourceforge.stripes.controller.ExecutionContext.wrap(ExecutionContext.java:74) 
     at net.sourceforge.stripes.controller.DispatcherHelper.invokeEventHandler(DispatcherHelper.java:440) 
     at net.sourceforge.stripes.controller.DispatcherServlet.invokeEventHandler(DispatcherServlet.java:278) 
     at net.sourceforge.stripes.controller.DispatcherServlet.service(DispatcherServlet.java:160) 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at net.sourceforge.stripes.controller.StripesFilter.doFilter(StripesFilter.java:247) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) 
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849) 
     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) 
     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454) 
     at java.lang.Thread.run(Thread.java:595) 
Caused by: java.sql.BatchUpdateException: Deadlock found when trying to get lock; try restarting transaction 
     at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:657) 
     at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723) 
     at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) 
     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) 
     ... 48 more 
org.springframework.orm.jpa.JpaTransactionManager:893 - Initiating transaction rollback after commit exception 
org.springframework.dao.CannotAcquireLockException: Could not execute JDBC batch update; SQL [update application_instances set application_id=?, create_date=?, for_ongoing_task=?, last_log_id=?, last_notified_date=?, name=?, param_string=?, application_status_id=?, status_date=? where id=?]; nested exception is org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update 
     at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:633) 
     at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:97) 
     at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:471) 
     at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) 
     at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) 
     at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:375) 
     at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
     at $Proxy66.create(Unknown Source) 
     at biz.cytrus.overlord.v2.web.action.task.LogAction.createLogEntry(LogAction.java:84) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:592) 
     at net.sourceforge.stripes.controller.DispatcherHelper$6.intercept(DispatcherHelper.java:442) 
     at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:158) 
     at net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor.intercept(BeforeAfterMethodInterceptor.java:113) 
     at net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:155) 
     at net.sourceforge.stripes.controller.ExecutionContext.wrap(ExecutionContext.java:74) 
     at net.sourceforge.stripes.controller.DispatcherHelper.invokeEventHandler(DispatcherHelper.java:440) 
     at net.sourceforge.stripes.controller.DispatcherServlet.invokeEventHandler(DispatcherServlet.java:278) 
     at net.sourceforge.stripes.controller.DispatcherServlet.service(DispatcherServlet.java:160) 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at net.sourceforge.stripes.controller.StripesFilter.doFilter(StripesFilter.java:247) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) 
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849) 
     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) 
     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454) 
     at java.lang.Thread.run(Thread.java:595) 
Caused by: org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update 
     at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:105) 
     at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) 
     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266) 
     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168) 
     at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) 
     at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) 
     at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027) 
     at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365) 
     at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137) 
     at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54) 
     at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467) 
     ... 39 more 
Caused by: java.sql.BatchUpdateException: Deadlock found when trying to get lock; try restarting transaction 
     at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:657) 
     at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723) 
     at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) 
     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) 
     ... 48 more 
org.springframework.orm.jpa.JpaTransactionManager:488 - Rolling back JPA transaction on EntityManager [[email protected]] 
org.springframework.orm.jpa.JpaTransactionManager:548 - Closing JPA EntityManager [[email protected]] after transaction 
org.springframework.orm.jpa.EntityManagerFactoryUtils:329 - Closing JPA EntityManager 

この問題を解決するための試みにおいて、私は、トランザクションの注釈に分離レベルを設定しようとしたが、それはデータベースに活動なしになり:


org.springframework.orm.jpa.JpaTransactionManager:365 - Creating new transaction with name [biz.cytrus.overlord.v2.core.ExecutionLogAPI.create]: PROPAGATION_REQUIRED,ISOLATION_REPEATABLE_READ; '' 
org.springframework.orm.jpa.JpaTransactionManager:323 - Opened new EntityManager [[email protected]] for JPA transaction 
org.springframework.orm.jpa.EntityManagerFactoryUtils:329 - Closing JPA EntityManager 

この問題の解決方法については、本当に助けていただきたいと思います。

ここアノテーション@Transactionalでマークされたメソッドのコードの抜粋は次のとおり


Task task = ongoingTaskAPI.findById(taskId); 
ExecutionLog executionLog = new ExecutionLog(); 
executionLog.setStatusDate(new Date()); 
executionLog.setStatus(status); 

     executionLog.setApplicationInstance(task.getApplicationInstance()); 

executionLog.getApplicationInstance().setLastLog(executionLog); 
em.persist(executionLog); 

次のようにエンティティBeanの関連部分は以下のとおり


public class ExecutionLog implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Integer id; 

    @ManyToOne 
    @JoinColumn(name="application_instance_id") 
    private ApplicationInstance applicationInstance; 

public class ApplicationInstance implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Integer id; 

    @OneToOne 
    @JoinColumn(name="last_log_id", nullable = true) 
    private ExecutionLog lastLog; 

1どの時点でも1対1の関係が存在する場合、特定のログレコードは特定のアプリケーションインスタンスレコードにのみリンクできます。

本質的に、私がやっていることは、ログレコードを作成してから、それに関連する最新のログレコードにリンクされるようにアプリケーションインスタンスを更新することです。これは単一のトランザクション方式で行われますが、アプリケーションインスタンスレコードが更新されたときにエラーが発生したようです。ただし、これは1回の呼び出しで正常に動作しますが、同時呼び出しでは正常に動作しません。

これが私の質問にもっと明確になることを願っています。

+0

あなたが示すことができますいくつかのコード? – axtavt

+0

上記のコードスニペットを追加しました。 stacktraceによると、BatchUpdateExceptionは、アプリケーションインスタンスのログレコードを設定するem.persistの直前の行で発生します。 – Razeen

答えて

4

最新のログエントリを指している共有「アプリケーションインスタンス」行がロックの問題を要求しています。シーケンスが可能になるように私には思える:application_instanceから

  • 選択
  • execution_logに
  • 挿入、application_instanceを参照
  • 更新application_instance
  • (application_instance行に排他ロックをとる)(application_instance行の共有ロックがかかります)

したがって、2つのスレッドがapplication_instanceに共有ロックを持つことができます。スレッドAは次にスレッドBのブロックを更新しようとし、スレッドAのスレッドBブロックを返します。

これは、排他ロックでアプリケーションインスタンスをすぐに取得することで解決します。エンティティをロードするときにLockMode.UPGRADE(またはLockMode.PESSIMISTIC_WRITE)を指定することによって行われる直接的な休止状態(session.getまたはクエリ上)。

(あなたが実際にタイム最新のログエントリで、それぞれを指すようにapplication_instanceを更新する必要がある場合、私はまた、再検討されるすべての取引がそれにシリアライズ/同期させる必要があるとして、ボトルネックとなっている。)

+0

ああああああああああありがとう!それが私の問題を解決しました! :) – Razeen

関連する問題