java-使用多个线程更新数据库时,如何避免“锁定超时”?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java-使用多个线程更新数据库时,如何避免“锁定超时”?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5906字,纯文字阅读大概需要9分钟。
内容图文
我正在尝试使用多个线程更新表.但是我不是在同一时间更新相同的记录/行.我将表分为不同的组,并尝试同时更新它们.但是,我一直都收到锁定超时错误.
我正在使用Hibernate,Spring MVC,ThreadPoolTask??Executor和MySQL.我正在从另一个数据库模式中获取数据并更新自己的数据库.数据巨大,这就是为什么我要使用多线程,以便可以更快地完成.但是,它会产生“锁定超时”错误.有人可以帮忙吗?谢谢你的好心
我调用sessionFactory.getCurrenSession()来更新数据库表.
这是我的配置:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}">
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="WaitForTasksToCompleteOnShutdown" value="true" />
</bean>
这是我的堆栈跟踪:
WARN : org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1205, SQLState: 41000
ERROR: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Lock wait timeout exceeded; try restarting transaction
Exception in thread "taskExecutor-5" Exception in thread "taskExecutor-4" Exception in thread "taskExecutor-2" org.hibernate.exception.LockTimeoutException: could not execute statement
at org.hibernate.dialect.MySQLDialect$1.convert(MySQLDialect.java:407)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:136)
at org.hibernate.hql.internal.ast.exec.BasicExecutor.execute(BasicExecutor.java:103)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.executeUpdate(QueryTranslatorImpl.java:413)
at org.hibernate.engine.query.spi.HQLQueryPlan.performExecuteUpdate(HQLQueryPlan.java:282)
at org.hibernate.internal.SessionImpl.executeUpdate(SessionImpl.java:1289)
at org.hibernate.internal.QueryImpl.executeUpdate(QueryImpl.java:116)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1084)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4232)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4164)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2838)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2334)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2262)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2246)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:133)
... 25 more
解决方法:
总是会发生“锁定等待超时”(即使一次事务中插入大量插入内容),也没有解决方案.但是,当我尝试更新一个(相对较小的)表中的所有记录的一半而另一半正在由另一台服务器修改时,我设法解决了这一问题.
>查看事务中的所有SQL语句.
使用explain确保在可能的情况下使用索引.删除事务中不需要的所有语句.
>优化事务中SQL语句的顺序.
这对我来说是一个反复的尝试,但是尝试想象一下来自多个线程/连接的SQL语句的顺序对于数据库来说可能更容易处理.在我的情况下,只需切换两个SQL语句的顺序就可以减少“锁定等待超时”的发生.
>更新较小的子集.
这终于为我解决了“锁定等待超时”.在我的情况下,有一个索引列,使我可以将较大的更新集划分为较小的子集.因此,现在将一个大的更新事务转换为大约十个较小的更新事务.请记住,尽管您需要能够在崩溃后继续执行较小的事务(即数据必须保持一致,以便您的应用程序可以重做操作并获得相同的结果).
多个线程是否会提高吞吐量(每秒更新的行数)还有待观察:这取决于更新集的大小(网络延迟)以及MySQL处理表锁以更新表的效率.行.当使用两个线程/连接而不是一个时,您可能只会看到少量的改进.
[编辑]还请注意数据库触发器/过程:它们可能以不良的方式影响性能.
内容总结
以上是互联网集市为您收集整理的java-使用多个线程更新数据库时,如何避免“锁定超时”?全部内容,希望文章能够帮你解决java-使用多个线程更新数据库时,如何避免“锁定超时”?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。