Durante una recente attività da un Cliente, mi è stata presentata una problematica con un (ahimè !) ben noto preambolo: “SQL Server ha un bug !”. E’ vero, questo può accadere, ma l’esperienza insegna che spesso le conclusioni sono tratte in maniera affrettata, tanto più che è necessaria una conferma “ufficiale” da una persona Microsoft in grado di verificare la porzione di codice sorgente interessata. Perché questo cliente era così convinto ? Bè, ascoltando i sintomi riscontrati devo dire che tutti i torti non li aveva, giudicate Voi:

  •  Senza nessuna regolarità temporale, almeno in apparenza, il seguente messaggio di errore veniva loggato nell’ERRORLOG di SQL Server:
  •  

Error: 605, Severity: 21, State: 3.

Attempt to fetch logical page %S_PGID in database 2 failed.

It belongs to allocation unit %I64d not to %I64d.

  • Dopo qualche minuto (questo è importante !), ricevuto il relativo “alert”, Il DBA eseguiva una DBCC di “emergenza”, ma nessun errore era rilevato, l’output del tool era completamente pulito;

Errore 605 ? Molto brutto come tutti i DBA, che hanno avuto almeno un caso di corruzione di database nella vita, sanno bene ! Effettivamente non si può dare torto ad un DBA se la parola bug viene pronunciata, ma ad un esame più attento del messaggio di errore, il DBA doveva subito insospettirsi del fatto che la corruzione riguarda il database con ID = 2 e cioè il TEMPDB; pensateci bene:

  • Il database TEMPDB è il database “temporaneo” dell’istanza SQL Server;
  •  L’ERRORLOG registra un messaggio di errore relativo ad una possibile corruzione, ma il successivo (di qualche minuto !) controllo non trova nulla di anomalo;

Se sommate queste due cose insieme, quello che siete autorizzati a pensare è che la corruzione sia, per così dire, svanita perché l’oggetto in TEMPDB non esiste più…. In questo caso ci avete azzeccato, complimenti !

Quindi, direte Voi, è un bug !

Mi dispiace, so che tutte le persone Microsoft sono estremamente riluttanti ad ammetterlo, ed io non faccio eccezione, ma non è proprio così :-); dunque, il problema in oggetto è ben noto, si tratta effettivamente di un bug di SQL Server 2008 ma non di SQL Server 2008 R2 (la versione nel nostro caso), quindi tecnicamente:

  • E’ un bug di SQL Server 2008 perché c’è un articolo della Knowledge Base Microsoft che lo dice e che conferma che il problema è risolto con la “Cumulative Update 3” di SQL Server 2008 RTM:

FIX: You receive error 605 and error 824 when you run a query that inserts data into a temporary table in SQL Server http://support.microsoft.com/kb/960770/en-us

  • Non è un bug di SQL Server 2008 R2 perché il codice non è affetto dal problema in quanto versione successiva a quella in cui il problema è’ stato per la prima volta riscontrato e quindi fissato; faccio notare infatti che ai tempi del rilascio della CU3 per SQL Server 2008, la versione R2 ancora non era stata rilasciata !
  • 

La spiegazione di tutto è nella strategia adottata da Microsoft per “attivare” alcune fix che, sebbene risolvano effettivamente una certa classe di problemi, potrebbero impattare la compatibilità applicativa introducendo delle modifiche a come il “Query Optmizer” di SQL Server lavora: per non generare questo tipo di problemi, per una particolare e ristretta categoria di hotfix,  oltre ad installare una certa patch è anche necessario abilitare un particolare “trace flag” per rendere operativa la modifica già presente nel codice:

Trace flag 4199 is added to control multiple query optimizer changes previously made under multiple trace flags http://support.microsoft.com/kb/974006/en-us

Quindi, nel nostro caso con SQL Server 2008 R2 (versione RTM), la fix al problema era già inclusa nel codice del prodotto, ma non era attiva perché richiedeva l’attivazione mediante “trace flag”: dopo aver abilitato il trace flag “-T4135” (???) il problema non si è più ripresentato, evviva !

E’ stato un piacere, si è fatto tardi…. arrivederci e buon lavoro !

Ehi, un momento, frena: Microsoft, tu mi hai detto che la fix è già inclusa in SQL 2008 R2, che basta attivarla con il trace flag “-T4199” come dici nell’articolo, e poi usi un trace flag differente ? Ci devi una spiegazione !

Ci ho provato, ma mi è andata male ! :-)

Nel suddetto articolo, c’è una piccola nota, del tipo delle postille nei contratti di assicurazione o delle banche:

* Note In SQL Server 2008 R2 release version, the trace flag 4135 was inadvertently omitted from the list of trace flags that can be controlled by -T4199. But this has been fixed in Cumulative Update 1 for SQL Server 2008 R2. So, for this build and for SQL Server 2005 and SQL Server 2008 supported editions, -T4199 will suffice to enable this and other trace flags that are listed in this article.

A causa di un bug (ehm !), l’attivazione della fix per il problema doveva avvenire tramite trace flag “-T4199” ma non è stato così per cui nella versione “RTM” (pre CU1 per SQL Server 2008 R2), è necessario utilizzare un trace flag differente, cioè il “-T4135”. Se avete una versione eguale o successiva alla CU1 (per SQL Server 2008 R2) allora state tranquilli ed utilizzate il trace flag “-T4199”.

Stavolta, veramente, Vi auguro buon lavoro e mi congedo da Voi. Alla prossima !

- Igor Pagliai -

Le Opinioni espresse in questo blog sono strettamente personali e riflettono il punto di vista dell’autore/degli autori in base alla propria esperienza e conoscenza.

I contenuti di questo blog inoltre non rappresentano (necessariamente) le opinioni di Microsoft e non costituiscono alcuna garanzia ne’ conferiscono alcun diritto.