MySQL:尝试锁定

时间:2016-09-29 05:53:47

标签: mysql hibernate transactions atomikos

此配置会引发下一个异常:

  • MySQL 5.7.10
  • Spring 4.0.5
  • Hibernate 4.1.9
  • Atomikos 3.8.0
  • Spring ThreadPoolTask​​Executor介于10到20个线程之间

我需要Atomikos来处理两个数据库之间的交易。

例外是:

javax.persistence.PersistenceException: org.hibernate.exception.LockAcquisitionException: Deadlock found when trying to get lock; try restarting transaction
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:273)
    at com.app.writer.jta.dao.CustomerDAOImpl.findCustomer(CustomerDAOImpl.java:35)
    at com.app.writer.dao.impl.JTAPDFWriterDAO.saveBean(JTAPDFWriterDAO.java:64)
    at com.app.writer.item.writer.PDFWriter.write(PDFWriter.java:17)
    at org.springframework.batch.item.support.CompositeItemWriter.write(CompositeItemWriter.java:51)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy28.write(Unknown Source)
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:175)
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:151)
    at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$3.doWithRetry(FaultTolerantChunkProcessor.java:329)
    at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:263)
    at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:193)
    at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:217)
    at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.write(FaultTolerantChunkProcessor.java:422)
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:199)
    at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75)
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406)
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271)
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
    at org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate$ExecutingRunnable.run(TaskExecutorRepeatTemplate.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

我需要一个PROCESS权限来检查SHOW ENGINE STATUS以获取有关死锁的信息。

所以,我的问题是论文:

  • 登录... CustomerDAOImpl.findCustomer是获取查询和锁定表的键。但是,是因为这个查询/表还是另一个产生了死锁?
  • 与Atomikos的交易属于两个数据库。现在,我注意到所有相关的表都在InnoDB引擎中,除了MyISAM中的一个。这是正确的吗?可能是这个例外的原因吗?
  • 由于线程的数量,是否会发生死锁?

当然,非常感谢任何检查和分析此异常的帮助。

提前致谢

[已编辑] 罗希特的建议很好。我的下一步行动是:

  • 通过启用SHOW ENGINE STATUS并获取日志来获取有关死锁的更多信息。
  • 我的事务在UPDATE之前包含一些SELECT。我将从事务中提取查询,因此它只包含INSERT和UPDATE语句。

非常感谢。

1 个答案:

答案 0 :(得分:1)

1) ,查询(SELECT / INSERT / UPDATE / DELETE)可以锁定数据库。
例如:SELECT Query

SELECT * FROM CUSTOMER 

//Making use of nolock as below will avoid deadlock but there are chances that you may not get the recent records just insert in your DB.

SELECT * FROM (nolock)CUSTOMER 

2)当您使用两个或更多数据库时,事情会变得复杂,因为DB1将用于在其自身内运行查询(与DB1相关)并且DB2正在请求DB1触发一些查询(例如:通过触发器)。

例如: DB1 中,您首先将一些发送处理的记录(数据)保存到java应用程序中。 java应用程序使用 DB2 来存储所有处理单元(客户数据等),一旦应用程序完成任务并将处理单元保存在 DB1 中, DB1 通过触发器通知 DB2 现在任务已完成 这样可以正常工作,但随着DB服务器负载的增加,事情会变得复杂(多个线程执行n次事务),因此可能会出现死锁。

我猜,你每分钟都没有遇到死锁问题。一天可能是4-5次。这个问题在大型项目中很常见。此外,我猜你的事务会在发生死锁时回滚。

3)下面列出了几种最小化数据库中发生的死锁的方法 3.1)您可以通过处理org.hibernate.exception.LockAcquisitionException在DB中发生死锁后执行某些任务。
例如:发生死锁后,向您的论坛发送通知电子邮件。稍后,您必须手动重新启动事务。

3.2)您可以做的其他事情是数据库服务器优化(调整),这将帮助您在一定程度上最大限度地减少死锁。

3.3)通过控制数据库服务器上的负载。 数据库服务器上可以有两种类型的负载,如下所示:

  • 受控加载(排队处理,例如JMS,此处可以延迟处理单位的请求)。
  • 不受控制的负载(用户/客户正在访问您的数据库,此处您 >限制用户,因此在这种情况下无法执行任何操作。)