Sql 来自 java/hibernate 的服务器查询在循环中调用时随机超时

Sql Server query from java/hibernate randomly times out when called within a loop

我在尝试从对 sql 服务器的 java 调用执行 sql 查询时遇到了一个奇怪的问题。

对 java 函数的一次调用运行良好,但是当我在一个循环中(从 2 到 30 次迭代)执行相同的操作时,我有时(并非总是)遇到这样的错误:

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Le délai imparti à la requête a expiré. at com.microsoft.sqlserver.jdbc.TDSCommand.checkForInterrupt(IOBuffer.java:5918)

我注意到的几件事:

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

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 

一些其他信息

编辑 28/11:原因

在我的循环中的某个地方,不时插入来自查询项目的相同 table 的对象。它在单独的事务中执行(尽管我也尝试在同一事务中执行)。插入对象时的迭代不会出现问题,但在接下来的迭代中......现在,我有原因......我仍然不明白为什么这会导致下一次迭代失败......虽然我怀疑一旦我理解它就会非常明显!

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" 方法从循环内移到循环外就成功了...... 但是,尽管我找到了解决方案,但我仍然不明白为什么嵌入在其自己专用事务中的先前插入会导致此锁保持到下一次迭代和另一个事务中!...因此,如果您有提示:它们是仍然欢迎!

顺便说一下,这个 post 对我找出锁定了哪个对象帮助很大!

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