Ogni istanza di SQL Server ha due parametri che indicano la quantità minima e massima di memoria RAM da utilizzare. Se questi valori sono diversi, SQL Server allocherà il minimo all’attivazione dell’istanza, e allocherà altra memoria secondo le necessità, arrivando eventualmente a raggiungere la soglia massima, ma senza superarla. Inoltre, l’istanza di SQL Server comunica al sistema operativo che, all’occorrenza, può liberare spazio, cosicché quando il sistema non riesce a dare memoria ad altre applicazioni, chiede a SQL Server di liberarne un po’. In questo caso la quantità di memoria usata cala, rimanendo sempre sopra la soglia minima impostata.
Fin qui tutto bene.
Ma che succede quando ci sono più istanza di SQL server sulla stessa macchina? Supponiamo che nessuno abbia toccato le impostazioni sulla memoria, questa avranno i valori predefiniti, vale a dire che non c’è limite superiore alla quantità di memoria da allocare. Allora, le istanze allocheranno memoria RAM finché ne hanno bisogno, arrivando a occuparla anche tutta. Quando una istanza avrà ulteriore necessità di memoria, dovrà svuotare una parte della sua cache e riutilizzarla, senza allocarne altra.
Nel mio caso, una delle istanze è collegata ad un applicativo molto utilizzato, e l’altra ad uno usato di rado. Durante il periodo estivo, la seconda applicazione non è stata e la macchina riavviata. Quindi, dal riavvio, la prima ha allocato sempre più memoria e la seconda è rimasta al minimo. Poi, dopo la pausa estiva, gli utenti non sono riusciti ad usare la seconda applicazione: non vi erano messaggi d’errore se non qualche timeout dell’applicativo che si lamentava del database lento. La macchina però non era lenta: la CPU era poco utilizzata, il disco non era sovraccarico. La memoria era però tutta usata. Le query sulla seconda istanza erano in attesa di RESOURCE_SEMAPHORE, vale a dire che l’istanza non faceva neppure partire le query perché non aveva memoria sufficiente a preparare il piano d’esecuzione. Quelle sessioni era messe in attesa di allocare la memoria RAM, ma l’attesa non finiva mai perché la memoria era tutta usata dall’altra istanza.
La soluzione è stata di impostare il limite minimo di memoria per tutte le istanze, avendo cura che fosse sufficiente all’uso normale dell’applicativo. Per l’istanza principale, ho anche impostato il limite massimo, così da non utilizzare nuovamente 30Gb.