Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么从多线程向同一个表插入新记录时会出现死锁问题,_Java_Sql Server - Fatal编程技术网

Java 为什么从多线程向同一个表插入新记录时会出现死锁问题,

Java 为什么从多线程向同一个表插入新记录时会出现死锁问题,,java,sql-server,Java,Sql Server,原因:org.hibernate.exception.LockAcquisitionException:无法执行语句 atorg.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:123) 位于org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQL

原因:org.hibernate.exception.LockAcquisitionException:无法执行语句

atorg.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:123)

位于org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)

位于org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)

位于org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)

位于org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:178)

位于org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3356)

位于org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3229)

位于org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3630)

位于org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:146)

位于org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)

位于org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478)

位于org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356)

位于org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)

位于org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1454)

位于org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:511)

在org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3283)上

在org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2479)上

在org.hibernate.engine.jdbc.internal.jdbcoordinatorimpl.beforeTransactionCompletion(jdbcoordinatorimpl.java:473)上

位于org.hibernate.resource.transaction.backend.jdbc.internal.jdbResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(jdbResourceLocalTransactionCoordinatorImpl.java:178)

位于org.hibernate.resource.transaction.backend.jdbc.internal.jdbResourceLocalTransactionCoordinatorImpl.access$300(jdbResourceLocalTransactionCoordinatorImpl.java:39)

位于org.hibernate.resource.transaction.backend.jdbc.internal.jdbResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(jdbResourceLocalTransactionCoordinatorImpl.java:271)

位于org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:98)

位于org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:532)

。。。省略65个公共框架

原因:com.microsoft.sqlserver.jdbc.SQLServerException:事务(进程ID 52)在与另一个进程的锁|通信缓冲区资源上死锁,并被选为死锁受害者。重新运行事务

位于com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:232)

位于com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1672)

位于com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:460)

位于com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:405)

位于com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7535)

位于com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2438)

位于com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:208)

位于com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:183)

位于com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:348)

位于com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)

位于com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)

位于org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)

。。。省略了83个公共框架


什么是死锁?

当两个进程争夺对资源的独占访问权,但由于另一个进程正在阻止它而无法获得对该资源的独占访问权时,就会发生死锁。这将导致两个进程都无法继续的僵局。摆脱死锁的唯一方法是终止其中一个进程。SQL Server会自动检测何时发生死锁,并通过终止称为受害者的进程之一来采取行动

他们如何选择受害者?

SQL Server选择工作量较少的进程来回滚该进程

因此,在您的情况下,当您有多个线程从一个特定的表中获取数据时,它们会锁定该表,并且任何进程都不能同时访问该表。在您的情况下,如果有任何线程对一个表进行选择,同时试图在该表中插入记录,可能会导致死锁

您可以在此处找到更多信息:

如何预防?

您可以使用(nolock)将
添加到您的选择中,例如:

select * from table with(nolock)
如果要添加条件,应如下所示:

select * from table with(nolock) where id = x
糟糕的是,如果您在事务进行某些更改的确切时间内使用(nolock)
执行select
,则即使在事务回滚之后,您也会捕获这些更改