Recentemente ho affrontato alcun problemi legati all'hang di query distribuite che utilizzano linked server, creati con provider di terze parti, per accedere a sorgenti dati diverse da Sql Server.

Di seguito sono descritte le attività eseguite per individuare la causa e come risolvere i problemi.

Problema

  • In modalità casuale query utilizzanti linked server creati con provider di terze parti, rimangono in esecuzione senza mai terminare
  • In alcuni casi, dopo il verificarsi della prima query in hang, tutte le successive query utilizzanti lo specifico Linked server, rimangono nello stesso stato di hang
  • L'unica soluzione al problema consiste nel riavviare Sql Server
  • L'esecuzione di una select sulla sysprocesses mostra lo SPID, avente in esecuzione la query, in stato di running con attesa su oledb

Dati da raccogliere

  • Al fine di verificare l'effettiva attività rimasta in esecuzione all'interno di Sql server, catturare un mini dump o filtered dump del processo di Sql server

Di seguito il link su come utilizzare sqldumper per ottenere un filtered o mini dump
How to use the Sqldumper.exe utility to generate a dump file in SQL Server 2005

Mini-dump file that includes indirectly referenced memory
Sqldumper.exe ProcessID 0 0x0120:40

Filtered dump file
Sqldumper.exe ProcessID 0 0x8100
ProcessID, in questo specifico caso, è l'ID del processo di Sql server

  • Salvare il risultato di una select * from master..sysprocesses, per individuare facilmente il Thread Id avente in esecuzione la query.

Analisi dei dati e Soluzione

  • Installare i Debugging Tools for Windows
  • Aprire windbg
    start-->program files-->Debugging Tools for Windows—>windbg
  • Caricare i simboli pubblici
    Con Windbg aperto, selezionare File -->Symbols file path
    Inserire srv*c:\symbols*http://msdl.microsoft.com/download/symbols
  • Caricare il dump prodotto
    Con Windbg aperto , selezionare File -->Open Crash Dump, selezionare il dump precedentemente prodotto
  • Individuare all'interno del dump il Thread ID avente in esecuzione la query
    Da Windbg, eseguire il comando ~ per avere la lista dei numeri relativi ai Thread ID e Thread instance
    0:000> ~
    . 0 Id: 2304.1500 Suspend: 0 Teb: bffdf000 Unfrozen
    1 Id: 2304.141c Suspend: 0 Teb: bffdb000 Unfrozen
    2 Id: 2304.11f4 Suspend: 0 Teb: bffda000 Unfrozen


    Convertire in esadecimale il valore presente nella colonna sysprocesses.kpid in corrispondenza dello SPID avente in esecuzione la query verso linked server, tale valore sarà il ThreadID.
    Cercare il valore così ottenuto tra i Thread ID nella lista sopra visualizzata, tenendo conto che nella riga "
    2 Id: 2304.11f4 Suspend: 0 Teb: bffda000 Unfrozen", 11f4
    è il numero del Thread ID e 2 è numero del Thread Instance

    Da notare che a causa del thread switching, il Thread ID potrebbe cambiare velocemente

    Per capire la relazione tra Spid. kpid e Thread Instance consiglio il seguente documento
    INFO: How to Correlate Spid, Kpid, and Thread Instance
  • Posizionarsi sul thread eseguente la query tramite il comando
    ~~[ ThreadID]

    Nel caso del dump da me analizzato, il numero del ThreadID era 1890
    41 Id: 2304.1890 Suspend: 0 Teb: bff93000 Unfrozen

    Per cui ho eseguito il comando ~~[1890]
    0:000> ~~[1890]
    . 41 Id: 2304.1890 Suspend: 0 Teb: bff93000 Unfrozen
    Start: msvcr80!_endthreadex+0x61 (781329e1)
    Priority: 0 Priority class: 32 Affinity: ff
  • Visualizzare lo stack frame del thread tramite il comando k
    0:041> k
    # ChildEBP RetAddr
    00 0f13d4b8 7739bf53 ntdll!KiFastSystemCallRet
    01 0f13d4f0 7738965e user32!NtUserWaitMessage+0xc
    02 0f13d518 7739f762 user32!InternalDialogBox+0xd0
    03 0f13d7d8 7739f047 user32!SoftModalMessageBox+0x94b
    04 0f13d928 7739eec9 user32!MessageBoxWorker+0x2ba
    05 0f13d980 773d7d0d user32!MessageBoxTimeoutW+0x7a
    06 0f13d9b4 773c42c8 user32!MessageBoxTimeoutA+0x9c
    07 0f13d9d4 773c42a4 user32!MessageBoxExA+0x1b
    08 0f13d9f0 0cb13f41 user32!MessageBoxA+0x45
    09 0f13dad4 0cb180ac ThirdPartydriver!......
    0a 0f13db68 0cb1b196 ThirdPartydriver!......
    0b 0f13dbb4 0cb1b4e6 ThirdPartydriver!......

    Dallo stack sopra riportato, possiamo capire come il driver di terze party, rinominato come ThirdPartydriver, ha eseguito internamente a Sql server una message box, motivo per cui, il thread non può proseguire l'attività.

Con buona probabilità, il driver di terze party ha eseguito una message box in seguito ad un problema interno o errore verificatosi, per cui per continuare l'analisi del problema sarà necessario contattare il produttore del driver.

Raffaella Canobbio
Support Escalation Engineer
Microsoft Enterprise SQL Support