SQL Server查询在循环中调用时从Java/Hibernate中随机出口



我在尝试从Java调用到SQLServer的SQL查询时遇到了一个奇怪的问题。

对Java函数的单个调用很好,但是当我在循环中(2至30迭代)进行相同操作时,我有时(并非总是如此)会有这样的错误:

由:com.microsoft.sqlserver.jdbc.sqlserverexception:ledélaiincriparti - la requarte aExpiré。 在com.microsoft.sqlserver.jdbc.tdscommand.checkforinterrupt(iobuffer.java:5918)

我注意到的几件事:

  • 它总是在循环的同一步骤中失败,前提是迭代项目保持不变(例如,如果在15步的第7步中失败,它将始终在步骤7中失败!)
  • 如果我跳过或更改任何迭代项目,包括先前失败的项目,它将在另一个步骤中失败...并且在下一步中不会失败,但是 - 看起来像是 - 随机一个
  • 如果我将失败的查询(从调试)复制/粘贴到sqlquerybrowser中并执行:它可以使用
  • 如果我从SQL Server Profiler复制/粘贴了失败的查询:它有效!
  • 如果我从SQL Server查询浏览器中执行循环(迭代输入参数):它有效!
  • 如果我在Junit测试中执行循环,则只能在对序列上进行迭代:它也有效!
  • 在SQL Server Profiler中,我可以看到成功的请求需要200至600毫秒才能完成,而失败的一个毫无疑问需要15000毫秒(=当前配置的超时)
  • 当我更改超时时,查询会不断计时。

这是我尝试执行的,没有成功:

  • 每个步骤/查询一项交易
  • 更新服务器'连接超时'et'查询超时'通过sp_serveroption( exec sp_serveroption'myServer sqlexpress','connect timeout',45; )))
  • 更改 QUERYTIMEOUT 从Java
  • 更改SQL查询浏览器{server}>" properties">"高级">" Parallelism"
  • 的"查询等待"选项
  • 请勿丢弃临时表#MatchingDays
  • 将随机令牌添加到#MatchingDays,以防止并发冲突
  • 添加查询周围的开始/结束
  • 用waitfor延迟延迟延迟t
  • 延迟请求
  • 使用存储过程而不是持有请求的字符串
  • 从"最后"语句中执行齐平 避免会话。
  • 重新启动SQLServer Tomcat
  • 将驱动程序更新到MSSQL-JDBC 6.1.0.jre7
  • 使用实际的表代替临时表

java调用

它嵌入到单个交易中

final SessionImpl sess = (SessionImpl) this.getSessionFactory().openSession();
try (Connection conn = sess.connection(); Statement st = conn.createStatement();) {
    final NamedParameterPreparedStatement ps = NamedParameterPreparedStatement.createNamedParameterPreparedStatement(conn, aStringWithTheRequestBelow);
        // ... set parameters here ...
    ps.setQueryTimeout(15);
    final ResultSet rs = ps.executeQuery();
} catch (final SQLException ex) {
    LOG.error("parameter 1 :" + parameter1 + "etc.");
} finally {
    sess.close();
}

tsql查询

(我使它对脑和眼睛友好,但它的外观更加棘手;但是,基本上,您有这样的想法)

--DECLARE @date as DATE = '2017-09-03'; -- one of the input parameter set up from java.

IF OBJECT_ID('tempdb.dbo.#MATCHINGDAYS718567154','U') is not null 
DROP TABLE #MATCHINGDAYS718567154; -- RANDOM TOKEN HERE TO AVOID CONCURRENCY
WITH startDateTable AS ( 
    SELECT TOP 1 a.dateStart 
    FROM   someSelection
), 
endDateTable AS ( 
    SELECT TOP 1 endDate
    FROM   anotherSelection
), 
AllDays  AS ( 
    SELECT myFunc_getMaxDate(DATEADD(DAY,1,startDateTable.dateStart), DATEADD(dd, -30,@date))AS [Date] 
    FROM startDateTable 
    UNION ALL 
    SELECT    
    DATEADD(DAY, 1, [Date]) 
    from  AllDays 
    join endDateTable on 1=1 
     WHERE    [Date] < myFunc_getMinDate(DATEADD(dd, +7, @date),endDateTable.endDate)) 

-- build a temporary table with all days from startDate to endDate the recursive way
-- with a min -30 days before input date and 7 days after output date    
SELECT [Date] 
     INTO #MATCHINGDAYS718567154 
         FROM    AllDays 
     OPTION (MAXRECURSION 37) 
SELECT   
    manyFields
from MainTable
-- various joins
join #MATCHINGDAYS718567154 as MD on 1 = 1 
where 1 = 1
and -- etc... many clauses including some computed over MATCHINGDAYS718567154
order by someField
DROP TABLE #MATCHINGDAYS718567154 

其他一些信息

  • Java 1.7_071
  • Hibernate 4.3.4.Final
  • SQLServer Express 2014
  • tomcat 7
  • sqljdbc4 4.0

编辑28/11:原因

我的循环中的某个地方,不时插入来自查询项目的同一表的对象。它是在分开的交易中执行的(尽管我也试图在同一交易中执行它)。当对象插入对象时,问题不会发生在迭代上,但是在以下迭代中...现在,我有原因...我仍然不明白为什么这会导致下一次迭代的失败...尽管我怀疑一旦我理解它,这将是完全明显的!

someIterationOver(List<SomeObject> manyObjects){
    from(SomeObject mo : manyObjects){
        List<MyTableObject> myTableObjects = performMyBigQueryOver(mo.getSomeId());
        for(MyTableObject myTableSingleObject : myTableObjects){
            if(myTableSingleObject.matchesSomeCondition()){
                TableSingleObject aNewTableSingleObject = new TableSingleObject("newTableObject");
                // this will cause the problem in the next iteration
                saveTableObject(aNewTableSingleObject);
            }
        }
    }
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
private void saveTableObject(ableSingleObject aNewTableSingleObject){
    this.sessionFactory.getCurrentSession.save(aNewTableSingleObject); // works fine
}

...欢迎任何技巧!

最终,我设法使它起作用:将" savetableObject"方法从循环内部移动到外部的外部,做到了。但是,尽管我找到了一个解决方案,但我仍然不明白为什么以前的插入物嵌入了自己的专门交易中,导致该锁定在下一次迭代中,并在另一项交易中保持!...因此,如果您有提示:它们是:它们是:仍然欢迎!

顺便说一句,这篇文章帮助我发现了哪个对象已锁定!

@Jean:非常感谢您的许多问题,这些问题帮助我专注于核心原因!

最新更新