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() 调用