Quando ESX 5 e Hyper-V in Windows Server 2012 hanno rilasciato e modificato le limitazioni che esistevano in precedenza per le dimensioni delle macchine virtuali, ho saputo quasi immediatamente che avremmo visto che i carichi di lavoro di SQL Server con scalabilità verticale più grandi avrebbero iniziato a essere virtualizzati. Ho lavorato con diversi clienti nell'ultimo anno che stavano virtualizzando 16-32 server SQL principali per vari motivi, dalle strategie di ripristino di emergenza semplificate che corrispondevano al resto dell'azienda, al consolidamento e alla riduzione del costo totale di proprietà su hardware più recente piattaforme. Uno dei motivi del cambiamento di scalabilità con ESX 5+ è stata l'introduzione del NUMA virtuale (vNUMA) per gli ampi guest che superavano le dimensioni di un singolo nodo NUMA hardware. Con vNUMA, la VM guest è ottimizzata per adattarsi alla topologia hardware NUMA, consentendo al sistema operativo guest e a tutte le applicazioni compatibili con NUMA, come SQL Server, in esecuzione sulla VM di sfruttare le ottimizzazioni delle prestazioni NUMA, proprio come se fossero in esecuzione su un server fisico.
All'interno di VMware, una topologia vNUMA è disponibile su hardware versione 8 o successiva e viene configurata per impostazione predefinita se il numero di vCPU è maggiore di otto per il guest. È anche possibile configurare manualmente la topologia vNUMA per una macchina virtuale utilizzando opzioni di configurazione avanzate, che possono essere utili per le macchine virtuali a cui è allocata più memoria di quella che può fornire un nodo NUMA fisico, ma utilizza comunque otto o meno vCPU. Per la maggior parte, le impostazioni di configurazione predefinite funzionano per la maggior parte delle macchine virtuali che ho esaminato negli ultimi anni, ma ci sono alcuni scenari in cui la topologia vNUMA predefinita non è l'ideale e la configurazione manuale può fornire alcuni vantaggi. Di recente stavo lavorando con un client con un numero di 32 VM SQL Server vCPU con 512 GB di RAM allocati eseguendo un po' di ottimizzazione delle prestazioni in cui la topologia vNUMA non era nulla di simile a quanto previsto.
I server host della macchina virtuale in questo ambiente erano quattro processori socket E5-4650 a otto core e 1 TB di RAM, ciascuno dedicato a una singola macchina virtuale SQL Server durante le operazioni tipiche, ma con capacità disponibile per supportare due macchine virtuali in uno scenario di errore. Con questo layout hardware, sono presenti quattro nodi NUMA, uno per socket, e la configurazione VM prevista prevede anche la presentazione di 4 nodi vNUMA per una configurazione a 32 vCPU. Tuttavia, quello che ho trovato guardando i DMV in SQL Server è che non era così:
Figura 1 – Configurazione vNUMA errata
Come probabilmente puoi vedere nell'immagine, c'è qualcosa che non va nella configurazione NUMA su questo server. Ci sono quattro nodi di memoria all'interno di SQLOS e un solo nodo CPU, con tutte le vCPU allocate al suo interno. Ad essere assolutamente onesto, questo mi ha lasciato senza parole quando l'ho visto perché andava contro tutto ciò che sapevo su come SQLOS configurava le strutture interne all'avvio dell'istanza. Dopo aver esaminato un po' i file ErrorLog, Performance Monitor e Task Manager di Windows, ho scaricato una copia di CoreInfo da SysInternals e ho dato un'occhiata al layout NUMA segnalato a Windows.
Mappa da processore logico a socket:********———————— Socket 0
——–********—————- Socket 1
—————-********——– Presa 2
————————******** Presa 3
Processore logico su mappa del nodo NUMA:
******************************** Nodo NUMA 0
L'output di CoreInfo ha confermato che la VM presenta le 32 vCPU come 4 socket diversi, ma poi ha raggruppato tutte le 32 vCPU nel nodo NUMA 0. Osservando i contatori delle prestazioni di Windows Server 2012 sulla VM ho potuto vedere dal gruppo di contatori di memoria del nodo NUMA, che 4 nodi di memoria NUMA sono stati presentati al sistema operativo con la memoria distribuita uniformemente tra i nodi. Tutto questo era in linea con quello che stavo vedendo in SQLOS e potevo anche dire dalle voci ERRORLOG di avvio che la maschera della CPU per il nodo stava mascherando tutte le CPU disponibili nel nodo CPU 0, ma venivano creati quattro allocatori di pagine grandi, uno per ogni nodo di memoria.
22/09/2013 05:03:37,Server,Sconosciuto,Configurazione nodo:nodo 0:Maschera CPU:0x00000000ffffffff:0 Maschera CPU attiva:0x00000000ffffffff:0. Questo messaggio fornisce una descrizione della configurazione NUMA per questo computer. Questo è solo un messaggio informativo. Non è richiesta alcuna azione da parte dell'utente.22/09/2013 05:03:37,Server,Sconosciuto,Questa istanza di SQL Server è stata segnalata l'ultima volta utilizzando un ID processo 1596 il 22/09/2013 05:00:25 (locale) 22/09/2013 10:00:25 (UTC). Questo è solo un messaggio informativo; non è richiesta alcuna azione da parte dell'utente.
22/09/2013 05:03:35,Server,Sconosciuto,Pagina grande allocata:32 MB
22/09/2013 05:03:35,Server,Sconosciuto,Grande Pagina allocata:32 MB
22/09/2013 05:03:35,Server,Sconosciuto,Pagina grande allocata:32MB
22/09/2013 05:03:35,Server,Sconosciuto,Pagina grande allocata :32 MB
22/09/2013 05:03:35,Server,Sconosciuto,Utilizzo di pagine bloccate in Gestione memoria.
22/09/2013 05:03:35,Server,Sconosciuto,Rilevato 524287 MB di RAM. Questo è un messaggio informativo; non è richiesta alcuna azione da parte dell'utente.
22/09/2013 05:03:35,Server,Sconosciuto,SQL Server inizia con la base di priorità normale (=7). Questo è solo un messaggio informativo. Non è richiesta alcuna azione da parte dell'utente.
22/09/2013 05:03:35,Server,Sconosciuto,SQL Server ha rilevato 4 socket con 8 core per socket e 8 processori logici per socket 32 processori logici totali; utilizzando 32 processori logici basati sulla licenza di SQL Server. Questo è un messaggio informativo; Non è richiesta alcuna azione da parte dell'utente.
A questo punto ero sicuro che fosse qualcosa relativo alla configurazione della VM, ma non riuscivo a identificare quale fosse specificamente il problema poiché non avevo mai visto questo comportamento su altre VM di SQL Server ampie che avevo assistito client su VMware ESX 5+ nel passato. Dopo aver apportato un paio di modifiche alla configurazione a un server VM di prova che era disponibile, solo nessuna di esse ha corretto la configurazione vNUMA presentata all'interno della VM. Dopo aver chiamato il supporto VMware, ci è stato chiesto di disabilitare la funzione hotplug vCPU per la VM di test e vedere se il problema è stato risolto. Con l'hotplug disabilitato sulla VM, l'output di CoreInfo ha confermato che la mappatura vNUMA dei processori per la VM ora era corretta:
Mappa da processore logico a socket:********———————— Socket 0
——–********—————- Socket 1
—————-********——– Presa 2
————————******** Presa 3
Processore logico a mappa del nodo NUMA:
********———————— Nodo NUMA 0
——–********————— - NUMA Nodo 1
—————-********——– NUMA Nodo 2
————————******** Nodo NUMA 3
Questo comportamento è in realtà documentato nell'articolo della Knowledge Base di VMware (vNUMA è disabilitato se è abilitato l'hotplug VCPU), da ottobre 2013. Questa è stata la prima VM ampia per SQL Server con cui avevo lavorato in cui era abilitato l'hotplug vCPU ed è non è una configurazione tipica che mi aspetterei per una VM da 32 vCPU, ma faceva parte del modello standard utilizzato sul client e influiva sul loro SQL Server.
Effetti della disattivazione di vNUMA
La disabilitazione di vNUMA in questo modo potrebbe avere diversi effetti su un carico di lavoro, ma esistono due problemi specifici che potrebbero interessare SQL Server in modo specifico in questo tipo di configurazione. Il primo è che il server potrebbe avere problemi con gli accumuli di attesa di CMEMTHREAD poiché ci sono 32 vCPU allocate a un singolo nodo NUMA e il partizionamento predefinito per gli oggetti di memoria in SQLOS è per nodo NUMA. Questo problema specifico è stato documentato da Bob Dorr nel gruppo CSS di Microsoft nel post sul blog SQL Server 2008/2008 R2 su macchine più recenti con più di 8 CPU presentate per nodo NUMA potrebbe essere necessario il flag di traccia 8048. Come parte della revisione delle statistiche di attesa sulla macchina virtuale con il client ho notato che CMEMTHREAD era il secondo tipo di attesa più alto, il che è anormale dalla mia esperienza e mi ha fatto guardare la configurazione di SQLOS NUMA mostrata nella Figura 1 sopra. In questo caso il flag di traccia non è la soluzione, la rimozione dell'hotplug della vCPU dalla configurazione della VM risolve il problema.
Il secondo problema che interesserebbe SQL Server in particolare se si utilizza una versione senza patch è associato alla gestione della memoria NUMA in SQLOS e al modo in cui SQLOS tiene traccia e gestisce le pagine Assenti durante la fase iniziale di accelerazione della memoria dopo l'avvio dell'istanza. Questo comportamento è stato documentato da Bob Dorr nel post del blog CSS, How It Works:SQL Server (NUMA Local, Foreign and Away Memory Blocks). In sostanza, quando SQLOS tenta un'allocazione di memoria del nodo locale durante l'avvio iniziale, se l'indirizzo di memoria restituito proviene da un nodo di memoria diverso, la pagina viene aggiunta all'elenco Away e si verifica un altro tentativo di allocazione della memoria locale e il processo si ripete finché un'allocazione della memoria locale riesce o viene raggiunta la destinazione della memoria del server. Poiché tre quarti della memoria delle nostre istanze esiste su nodi NUMA senza utilità di pianificazione, ciò crea una condizione di prestazioni degradate durante l'aumento iniziale della memoria per l'istanza. Aggiornamenti recenti hanno modificato il comportamento dell'allocazione della memoria durante l'accelerazione iniziale per tentare l'allocazione della memoria locale solo un numero fisso di volte (il numero specifico non è documentato) prima di utilizzare la memoria esterna per continuare l'elaborazione. Tali aggiornamenti sono documentati in KB n. 2819662, FIX:problemi di prestazioni di SQL Server negli ambienti NUMA.
Riepilogo
Per le VM estese, definite come dotate di più di 8 vCPU, è consigliabile che vNUMA sia passato alla VM dall'hypervisor per consentire a Windows e SQL Server di sfruttare le ottimizzazioni NUMA all'interno della loro base di codice. Di conseguenza, queste VM più ampie non dovrebbero avere la configurazione hotplug vCPU abilitata, poiché ciò è incompatibile con vNUMA e può comportare un peggioramento delle prestazioni per SQL Server quando virtualizzato.