Leggete una riga del registro di SQL Server su un binding non riuscito mentre il servizio è ancora in esecuzione, e avete trovato una dipendenza dall’ordine di avvio, non un crash. È proprio quella combinazione l’indizio: il motore è partito prima che l’indirizzo su cui doveva ascoltare esistesse sulla macchina. Un adattatore VPN che compare dopo l’accesso è un pessimo prerequisito per un servizio di database senza supervisione, quindi ripercorrete il guasto nell’ordine in cui lo vede il motore.

Partite dal registro di avvio, non dal client

Aprite il registro errori dell’istanza e leggete le voci intorno all’inizializzazione di rete, non solo l’ultima riga. Il motore riporta quali indirizzi ha provato e quali protocolli ha abilitato, e quel record è precedente alla connessione di qualsiasi client. Ora guardate cosa esiste sull’host in questo momento. Se l’interfaccia che possiede l’indirizzo configurato compare solo dopo che un utente accede e avvia un client, l’indirizzo era assente all’avvio e il guasto del binding è del tutto spiegato.

Get-NetIPAddress -AddressFamily IPv4 | Select-Object InterfaceAlias, IPAddress, PrefixOrigin
Get-Content 'C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\LOG\ERRORLOG' -Tail 40

Adattate il percorso dell’istanza alla vostra installazione e leggete l’elenco delle interfacce prima di trarre conclusioni. Un indirizzo che esiste ma appartiene all’adattatore sbagliato è un problema diverso da un indirizzo che non esiste ancora.

Ripercorrete l’ordine di binding che il motore segue davvero

Il motore legge la configurazione del listener e poi chiede al sistema operativo di eseguire il binding. Se l’indirizzo non è locale in quel momento, il binding fallisce per quell’indirizzo mentre il resto dell’istanza può continuare normalmente. È per questo che altri protocolli o altri indirizzi possono ancora funzionare, ed è per questo che «SQL Server è giù» è il riassunto sbagliato. Conservate l’endpoint esatto dal registro: indirizzo, porta e protocollo, perché la correzione dipende da quale dei tre è sbagliato.

Riavviare il servizio dopo la comparsa dell’adattatore di solito fa riuscire il listener, ed è esattamente la trappola. Dimostra la dipendenza invece di rimuoverla, e interrompe ogni utente connesso ogni volta che il tunnel si riconnette.

Leggete il listener come lo legge il motore

In SQL Server Configuration Manager aprite le proprietà TCP/IP dell’istanza e notate l’impostazione Listen All prima di modificare i singoli indirizzi. Quando Listen All è Yes, i valori Enabled per indirizzo vengono ignorati, quindi modificarli non cambia nulla di ciò che usa il listener. Annotate tre cose in ordine: l’indirizzo che intendete servire, la porta e se il listener deve coprire tutti gli indirizzi o solo uno. Poi applicate la modifica con la procedura di riavvio supportata e leggete il registro di avvio successivo per confermare che il motore ha eseguito il binding richiesto.

Ascoltare su ogni indirizzo non è controllo degli accessi. Se un listener ampio è davvero necessario, ogni interfaccia raggiungibile ha bisogno della propria decisione su firewall e autorizzazione del database, compresa qualsiasi interfaccia rivolta a internet.

Date al client una destinazione stabile

Il client non ha bisogno che l’host del database indossi un indirizzo del pool. Un progetto instradato funziona con il server in ascolto sul suo indirizzo privato stabile mentre il gateway VPN inoltra il traffico del client verso di esso e riporta la risposta.

Test-NetConnection -ComputerName 10.80.0.15 -Port 1433
tracert -d 10.80.0.15

Se il client raggiunge 10.80.0.15, il percorso è dimostrato e il database deve solo autorizzare quel client. In caso contrario, correggete routing e DNS prima di toccare di nuovo il listener, perché un problema di binding sul server non è mai stato il motivo per cui un client non riesce a trovarlo. Aggiungere un falso indirizzo del pool al server, o un secondo gateway predefinito per accontentare il listener, crea un nuovo problema di rete sopra quello vecchio. Mantenete statico l’indirizzamento del server e lasciate che il tunnel porti i client fino a lui.

Verificate l’endpoint usato dal client

Concludete con un controllo a livello applicativo invece di un test della porta. Connettetevi dal client con l’account usato dall’applicazione e leggete i dettagli di connessione lato server, che mostrano l’indirizzo locale su cui è atterrata la sessione.

sqlcmd -S tcp:10.80.0.15,1433 -Q "SELECT local_net_address, local_tcp_port FROM sys.dm_exec_connections WHERE session_id = @@SPID"

Confrontate quell’indirizzo con il listener configurato. Una discrepanza significa un secondo listener o un nome risolto in un punto inatteso, ed entrambi vale la pena conoscerli prima che il prossimo riavvio metta alla prova la vostra correzione al posto vostro. Poi riavviate l’host senza utenti connessi e confermate che il binding riesce. Quell’unico test è la differenza tra un listener riparato e una soluzione provvisoria che fallisce la prossima notte di patch.

Articoli correlati