Sql Server 2012 上的“不允许启动新请求,因为它应该带有有效的事务描述符”

Posted

技术标签:

【中文标题】Sql Server 2012 上的“不允许启动新请求,因为它应该带有有效的事务描述符”【英文标题】:"New request is not allowed to start because it should come with valid transaction descriptor" on Sql Server 2012 【发布时间】:2017-08-17 11:59:46 【问题描述】:

编辑:找到解决方案,往下看。

我们有一个 Web 应用程序,它调用存储在 Sql Server 2012 数据库中的视图的选择。

此查询失败并出现错误

"New request is not allowed to start because it should come with valid transaction descriptor"

此问题仅发生在单个客户数据库上,在所有其他客户架构上执行的相同查询运行正常。

在 SSMS 中对受影响的架构自行执行的查询运行正常,仅在该特定架构上的应用程序中失败。

SELECT 语句是这样的:

select distinct clienti.numeroCliente,clienti.ragioneSociale,clienti.partitaIva,clienti.codiceFiscale,
clienti.SedeLegale,
clienti.mail,clienti.codiceContabilita,clienti.riferimentiCliente
 from dbo.view_table clienti
where clienti.azienda = 'Company_name'

如果我们在其他 Sql Server 实例上本地恢复架构,我们可以复制错误。

我在互联网上进行了很多搜索,发现的只是 Sql Server 2005 的一个修补程序 (https://support.microsoft.com/en-us/help/939285/fix-error-message-when-you-run-a-stored-procedure-that-starts-a-transaction-that-contains-a-transact-sql-statement-in-sql-server-2005-new-request-is-not-allowed-to-start-because-it-should-come-with-valid-transaction-descriptor) 以及一些与分布式查询和索引碎片相关的帖子。

鉴于我可以复制问题,我可以尝试解决什么问题?

运行查询的spring后端是Java,通过Hibernate运行的原生sql查询。

Java 8

春季 4.1.1

休眠 4.3.5

这是代码:

@Transactional(readOnly=true, isolation=Isolation.READ_UNCOMMITTED)
    public List<ControlloContratto> caricaControlloContratti(FilterControlloContratti filter) 
        List<ControlloContratto> lstCtrlContratti = null;

            String dwhExtractionCCPQuery = "";

            Session session = sessionManager.getFilteredSession(FilterType.NONE);
            dwhExtractionCCPQuery = caricaControlloContrattiQuery(filter);
            Query queryCallSP = session.createSQLQuery(dwhExtractionCCPQuery);

            queryCallSP.setResultTransformer(Transformers.aliasToBean(ControlloContratto.class));
            lstCtrlContratti = queryCallSP.setReadOnly(true).list();

            

我尝试去掉自定义的隔离级别和只读注解,结果是一样的。

编辑:添加用于创建被调用视图的脚本

CREATE VIEW [dbo].[e3_dwh_view_clienti] AS
SELECT COALESCE(azienda.nome,'') azienda,
       cliente.id idCliente,
       cliente.numero numeroCliente,
       cliente.ragione_sociale ragioneSociale,
       COALESCE(cliente.partita_iva,'') partitaIva,
       COALESCE(cliente.codice_fiscale,'') codiceFiscale,
       natura.descrizione naturaCliente,
       COALESCE((CASE WHEN tipoVia.descrizione IS NOT NULL AND pntStrad.fk_e0_decod_viario IS NULL
            THEN tipoVia.descrizione 
             WHEN tipoVia.descrizione IS NULL AND pntStrad.fk_e0_decod_viario IS NULL
            THEN ''
             ELSE tipoVia2.descrizione 
         END),'') toponimo,
       COALESCE((CASE WHEN tipoVia.descrizione IS NOT NULL AND pntStrad.fk_e0_decod_viario IS NULL
            THEN pntStrad.indirizzo + ' ' + (CASE WHEN pntStrad.numero_civico IS NULL THEN '' ELSE pntStrad.numero_civico END)
              + (CASE WHEN pntStrad.esponente_civico IS NULL THEN '' ELSE '/'+pntStrad.esponente_civico END) 
             WHEN tipoVia.descrizione IS NULL AND pntStrad.fk_e0_decod_viario IS NULL
            THEN  pntStrad.indirizzo + ' ' + (CASE WHEN pntStrad.numero_civico IS NULL THEN '' ELSE pntStrad.numero_civico END)
              + (CASE WHEN pntStrad.esponente_civico IS NULL THEN '' ELSE '/'+pntStrad.esponente_civico END)
             ELSE viario.denominazione + ' ' + (CASE WHEN pntStrad.numero_civico IS NULL THEN '' ELSE pntStrad.numero_civico END)
              + (CASE WHEN pntStrad.esponente_civico IS NULL THEN '' ELSE '/'+pntStrad.esponente_civico END)
         END),'') indirizzo,
       COALESCE(cap.codice,COALESCE(comune.cap,'')) cap,
       COALESCE(comune.comune,'') comune, 
       COALESCE(comune.provincia,'') provincia,
       COALESCE((CASE WHEN tipoVia.descrizione IS NOT NULL AND pntStrad.fk_e0_decod_viario IS NULL
    THEN tipoVia.descrizione + ' ' + pntStrad.indirizzo + ' ' + (CASE WHEN pntStrad.numero_civico IS NULL THEN '' ELSE pntStrad.numero_civico END)
      + (CASE WHEN pntStrad.esponente_civico IS NULL THEN '' ELSE '/'+pntStrad.esponente_civico END) +  ', ' + 
        (CASE WHEN cap.codice IS NULL THEN '' ELSE cap.codice END)+ ' '+ (CASE WHEN comune.comune IS NULL THEN '' ELSE comune.comune END)
     WHEN tipoVia.descrizione IS NULL AND pntStrad.fk_e0_decod_viario IS NULL
    THEN  pntStrad.indirizzo + ' ' + (CASE WHEN pntStrad.numero_civico IS NULL THEN '' ELSE pntStrad.numero_civico END)
      + (CASE WHEN pntStrad.esponente_civico IS NULL THEN '' ELSE '/'+pntStrad.esponente_civico END) +  ', ' + 
        (CASE WHEN cap.codice IS NULL THEN '' ELSE cap.codice END)+ ' '+ (CASE WHEN comune.comune IS NULL THEN '' ELSE comune.comune END)
     ELSE tipoVia2.descrizione + ' ' + viario.denominazione + ' ' + (CASE WHEN pntStrad.numero_civico IS NULL THEN '' ELSE pntStrad.numero_civico END)
      + (CASE WHEN pntStrad.esponente_civico IS NULL THEN '' ELSE '/'+pntStrad.esponente_civico END) +  ', ' + 
        (CASE WHEN cap.codice IS NULL THEN '' ELSE cap.codice END)+ ' '+ (CASE WHEN comune.comune IS NULL THEN '' ELSE comune.comune END)
  END),'') SedeLegale,
        CAST(cliente.data_cliente_dal AS DATE) dataClienteDal,
        CAST(cliente.dt_inserimento AS DATE) dataInserimento,
        CAST(cliente.dt_modifica AS DATE) dataModifica,
       COALESCE(cliente.nome,'') nome,
       COALESCE(cliente.cognome,'') cognome,
       CAST(COALESCE((SELECT DISTINCT 1 FROM e2_com_contratti k
          JOIN e2_com_prestazioni p ON p.fk_e2_com_contratto  = k.id
         WHERE k.fk_e2_com_cliente = cliente.id 
           AND k.fk_e0_prof_nodo = cliDett.fk_e0_prof_nodo
           AND p.dt_scadenza >= GETDATE()),0) AS BIT) flagAttivo,
       CAST(cliente.fl_piva_duplicata AS BIT) flagPartIvaDupl,
       CAST(cliente.fl_spacement_firma AS BIT) flagSpacement,
       CAST(cliente.fl_importante AS BIT) flagImportante,
       CAST(cliente.fl_mail_fattura AS BIT) flagMail,
       CAST(COALESCE(STUFF((SELECT '; '+ COALESCE(mail.email,'') 
        FROM (
            SELECT DISTINCT c.id,n.id nodo,c.mail_cliente  email FROM e2_com_clienti c
            JOIN e0_prof_nodi n ON n.fk_e0_prof_tipo_nodo = 1
            WHERE c.mail_cliente <> ' '
            UNION
            SELECT DISTINCT c.id,d.fk_e0_prof_nodo nodo,d.mail_fattura email FROM e2_com_clienti c
            JOIN e2_com_contab_clienti_dett d ON d.fk_e2_com_cliente = c.id
            WHERE d.mail_fattura <> ' '
            UNION
            SELECT DISTINCT c.id,w.fk_e0_prof_nodo nodo,w.indirizzo_mail email FROM e2_com_clienti c
            JOIN e2_amm_wizard_fatture w ON w.fk_e2_com_clienti = c.id 
            WHERE w.indirizzo_mail <> ' '
            ) mail
       WHERE mail.id = cliente.id
         AND mail.nodo = cliDett.fk_e0_prof_nodo
       FOR XML PATH ('')),1,2,''),'') AS VARCHAR(MAX)) mail,
       CAST(cliente.fl_fax_fattura AS BIT) flagFax,
       COALESCE(cliente.fax_fattura,'') fax,
       CAST(cliente.fl_postalizzazione AS BIT) flagPosta,
       CAST(cliente.fl_sogg_ritenuta AS BIT) flagRitenuta,
       COALESCE(ritenuta.descrizione,'') ritenAcconto,
       COALESCE(cliDett.conto_cliente,'') contoCliente,
       COALESCE(cliDett.codice_contabilita,'') codiceContabilita,
       CAST(COALESCE(cliDett.fl_dichiarazione_intenti,0) AS BIT) flagDicIntenti,
       COALESCE(cliDett.numero_dic_int,'') numDicIntenti,
        CAST(cliDett.dt_rilascio_dic_int AS DATE) dataRilascioDicIntenti,
        CAST(cliDett.dt_decorrenza_dic_int AS DATE) dataDecorDicIntenti,
        CAST(cliDett.dt_scadenza_dic_int AS DATE) dataScadDicIntenti,
       CAST(COALESCE(cliDett.fl_importante_fatt,0) AS BIT) flagImportanteFatt,
       CAST(COALESCE(cliDett.fl_autocertif_f24,0) AS BIT) flagAutoCertF24,
       CAST(COALESCE(cliDett.fl_cliente_contabilizzato,0) AS BIT) flagCliContab,
       COALESCE(canale.descrizione,'') canale,
       COALESCE(grInd.descrizione,'') gruppoInd,
       COALESCE(segComm.descrizione,'') segComm,
       COALESCE(ateco.descrizione,'') categMerceologica,
       COALESCE(cliente.note,'') noteCliente,
       CAST(COALESCE(STUFF((SELECT DISTINCT '; ' + COALESCE(g.nome,'')
                FROM e2_com_gestori_clienti gc
                JOIN e0_decod_gestori g ON g.id = gc.fk_e2_com_gestore
               WHERE gc.fk_e2_com_cliente = cliente.id
               FOR XML PATH ('')),1,2,''),'') AS VARCHAR(MAX)) gestoreCliente,
       CAST(COALESCE(STUFF((SELECT DISTINCT '; ' + COALESCE(ic.codice,'') + ' ('+COALESCE(ic.codice_mandato,'')+')'
                FROM e2_com_iban_cliente_dett ic
               WHERE ic.fk_e2_com_cont_cliente = cliDett.id
               FOR XML PATH ('')),1,2,''),'') AS VARCHAR(MAX)) ibanCliente,
       CAST(COALESCE(STUFF((SELECT DISTINCT '; ' + cc.nome + ' - ' + tcc.recapito
                FROM e2_com_contatti_clienti cc
                JOIN e2_com_tipo_contatti_cliente tcc ON tcc.fk_e2_com_contatto_cliente = cc.id
               WHERE cc.fk_e2_com_cliente = cliente.id
               FOR XML PATH ('')),1,2,''),'') AS VARCHAR(MAX))riferimentiCliente,
        CAST(COALESCE(STUFF((SELECT '; '+ modiPag.descrizione 
                FROM (
                    SELECT DISTINCT c.id,w.fk_e0_prof_nodo,mp.descrizione FROM e2_com_clienti c
                    JOIN e2_amm_wizard_fatture w ON w.fk_e2_com_clienti = c.id 
                    JOIN e0_decod_modi_pagamento mp ON mp.id = w.fk_e0_decod_modo_pagamento
                    JOIN e2_com_contratti k ON k.fk_e2_com_cliente = c.id AND k.fk_e0_prof_nodo = w.fk_e0_prof_nodo
                    JOIN e2_com_prestazioni p ON p.fk_e2_com_contratto = k.id AND p.codiceAggregazione = w.codice_aggregazione
                    WHERE p.dt_scadenza >= GETDATE()) modiPag
               WHERE modiPag.id = cliente.id
                 AND modiPag.fk_e0_prof_nodo = cliDett.fk_e0_prof_nodo
               FOR XML PATH ('')),1,2,''),'') AS VARCHAR(MAX)) modoPagamento,
       COALESCE(statoCredCliente.descrizione,'') statoCreditoCliente,
       COALESCE(iva.descrizione,'') aliquotaIva,
       CAST(COALESCE(STUFF((SELECT '; '+ COALESCE(codPA.codUnivoco,'')
        FROM (
            SELECT c.id,k.fk_e0_prof_nodo,k.cod_destinatario  codUnivoco FROM e2_com_clienti c
            JOIN e2_com_contratti k ON k.fk_e2_com_cliente = c.id
            WHERE k.fk_e0_decod_stato_contratto = '1'
            UNION
            SELECT c.id,d.fk_e0_prof_nodo,d.cod_destinatario codUnivoco FROM e2_com_clienti c
            JOIN e2_com_contab_clienti_dett d ON d.fk_e2_com_cliente = c.id
            UNION
            SELECT c.id,w.fk_e0_prof_nodo,w.cod_destinatario codUnivoco FROM e2_com_clienti c
            JOIN e2_amm_wizard_fatture w ON w.fk_e2_com_clienti = c.id 
            ) codPA
       WHERE codPA.id = cliente.id
         AND codPA.fk_e0_prof_nodo = cliDett.fk_e0_prof_nodo
       FOR XML PATH ('')),1,2,''),'') AS VARCHAR(MAX)) codiceUnivocoPA
  FROM e2_com_clienti cliente 
  JOIN e0_conf_natura_clienti natura ON natura.id = cliente.fk_e0_natura_cliente
    LEFT JOIN e2_com_contab_clienti_dett cliDett ON cliDett.fk_e2_com_cliente = cliente.id AND cliDett.fl_cliente = 1
    LEFT JOIN e0_prof_nodi azienda ON azienda.id = cliDett.fk_e0_prof_nodo
    LEFT JOIN e0_decod_ritenuta ritenuta ON ritenuta.id = cliDett.fk_e0_decod_ritenuta
    LEFT JOIN e0_decod_tipi_cliente canale ON canale.id = cliente.fk_e0_decod_tipo_cliente
    LEFT JOIN e0_decod_gr_ind_com grInd ON grInd.id = cliente.fk_e0_decod_gp_ind_com
    LEFT JOIN e0_decod_segmento_com segComm ON segComm.id = cliente.fk_e0_decod_seg_com
    LEFT JOIN e0_decod_codici_ateco ateco ON ateco.id = cliente.fk_e0_decod_codice_ateco
    LEFT JOIN e2_com_ubicazioni_clienti sede ON sede.fk_e2_com_cliente = cliente.id AND sede.fl_primario = 1
    LEFT JOIN e2_com_punti_stradario pntStrad ON sede.fk_e2_com_pt_stradario = pntStrad.id
    LEFT JOIN e0_conf_tipi_via tipoVia ON pntStrad.fk_e0_decod_tipo_via = tipoVia.id
    LEFT JOIN e0_conf_comuni_cap cap ON pntStrad.fk_e0_conf_cap_comune = cap.id
    LEFT JOIN e0_conf_comuni comune ON cap.fk_e0_conf_comune = comune.codice_catastale
    LEFT JOIN e0_conf_viario viario ON pntStrad.fk_e0_decod_viario = viario.id
    LEFT JOIN e0_conf_tipi_via tipoVia2 ON viario.fk_e0_decod_tipo_via = tipoVia2.id
    LEFT JOIN e0_decod_stati_clienti statoCredCliente ON statoCredCliente.id = cliDett.fk_e0_decod_stato_cliente
    LEFT JOIN e0_decod_iva iva ON iva.id = cliDett.fk_e0_decod_iva
  WHERE cliente.fl_cliente = 1

谢谢

编辑 2:解决方案

经过多次尝试,我们了解到问题不是来自视图上的选择,而是来自在同一事务中执行的另一个查询,即在此方法之后调用的查询:

dwhExtractionCCPQuery = caricaControlloContrattiQuery(filter);

这个方法调用了一个存储过程,它只在这个特定的模式上被窃听,简而言之,它最后有一个错误的插入。 取下插件解决了问题!

【问题讨论】:

数据库中设置的隔离级别是多少? 我运行了这个 SELECT CASE transaction_isolation_level WHEN 0 THEN 'Unspecified' WHEN 1 THEN 'ReadUncommitted' WHEN 2 THEN 'ReadCommitted' WHEN 3 THEN 'Repeatable' WHEN 4 THEN 'Serializable' WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL FROM sys.dm_exec_sessions where session_id = @@SPID 并得到:“READ COMMITTED” 您可以尝试“使用(nolock)”查询提示运行您的查询吗? 您的问题可能是表值函数中的错误。如果您的源表被引用为 dbo.view_table 这一事实意味着它是一个返回表的 UDF,这可能适用。一个遇到同样错误的人报告说:“我需要做的就是修复表值函数,它抛出了一个数据类型转换错误。(我做了一个快速的修改,没有在更大的范围之外测试它查询。)”显然,如果您不使用 UDF(如果 dbo.view_table 是视图,请确保该视图未使用 UDF 或收到错误的数据类型错误),那么这可能不适用。 很高兴看到你把它整理好了! :) 【参考方案1】:

经过多次尝试,我们了解到问题不是来自视图上的选择,而是来自在同一事务中执行的另一个查询,即在此方法之后调用的查询:

dwhExtractionCCPQuery = caricaControlloContrattiQuery(filter);

这个方法调用了一个存储过程,它只在这个特定的模式上被窃听,简而言之它在存储过程的末尾有一个错误的插入

我们分步找到了解决方案:

1 - 首先我们发现在同一个@transactional 方法中有两个不同的查询,第一个是存储过程的执行,第二个是视图上的选择

2 - 我们将查询划分为 2 个独立的 @transactional 方法

3 - 发现这是第一个崩溃的查询

4 - 分析存储过程以找出与其他工作模式的差异

5 - 找到错位的插入物

删除插件解决了问题!

【讨论】:

以上是关于Sql Server 2012 上的“不允许启动新请求,因为它应该带有有效的事务描述符”的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2012 上的可插入 UNION ALL VIEW

XACT_ABORT 不回滚 SQL Server 2012 上的事务

无法通过 Windows 2012 上的系统 dsn 使用 ODBC 连接连接到 SQL Server 2008

致命错误:对 SQL SERVER 2012 的非对象 XAMPP 上的成员函数 query() 调用

sql server 2012复制数据库在同一主机上的两个实例之间失败

UPDATE 上的 SQL Server 死锁