SQL Server 2019 : « Max Server Memory » qui se réinitialise après reboot — causes, diagnostic, correctifs

Après chaque redémarrage, votre SQL Server 2019 remet « Max Server Memory » à 24 Go alors que vous visez 16 Go ? Voici un guide concret pour comprendre la cause, corriger durablement, et prévenir tout nouveau retour en arrière.

Sommaire

Changement automatique du paramètre Max Memory après reboot : vue d’ensemble

Symptôme : après chaque redémarrage, la valeur max server memory revient de 16 Go (souhaité) à 24 Go (non désiré). Objectif : identifier l’origine de ce « reset », appliquer le bon correctif et garantir la persistance de la configuration.

Réponse & solutions — plan d’action

ÉtapeActionDétails utiles
1. Vérifier la configuration effectiveEXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'max server memory (MB)';Confirme si la valeur « configurée » et la valeur « en cours » sont bien celles attendues.
2. Appliquer la limite de façon permanenteEXEC sp_configure 'max server memory (MB)', 16384; -- 16 Go RECONFIGURE;Nécessite un compte SA ou un rôle sysadmin. Redémarrage non obligatoire, mais utile pour valider la persistance.
3. Rechercher les sources qui ré‑appliquent 24 GoScripts de post‑installation dans …\MSSQL\Install Tâches planifiées, jobs SQL Agent, procédures de démarrage, déclencheurs DDL Politiques PBM, GPO ou solutions DSC/Puppet/Ansible Clé Registre : HKLM\Software\Microsoft\Microsoft SQL Server\<InstanceID>\MSSQLServer\ (Max Server Memory)Toute automatisation ou stratégie de conformité peut écraser votre modification manuelle.
4. Mettre la clé Registre en cohérenceModifier la valeur décimale (en Mo) puis redémarrer le service SQL Server.Évite qu’une valeur divergente enregistreur/démarrage n’écrase à nouveau le paramètre.
5. Valider la bonne pratique mémoireLaisser 2‑4 Go à l’OS Fixer min server memory quelques Go en‑dessous de max Surveiller sys.dm_os_process_memory et PerfMon « SQL Server:Memory Manager »Garantit des performances stables et évite la contention mémoire.

Pourquoi la valeur revient‑elle à 24 Go ?

Plusieurs causes typiques :

  • Automatisation : un script de provisioning, un runbook DevOps (DSC/Ansible/Puppet), une GPO ou une politique PBM peut réappliquer 24 Go à chaque démarrage.
  • Valeur de Registre divergente : au démarrage, SQL Server lit la configuration dans le Registre Windows. Si la clé porte 24576 Mo, la valeur en cours sera 24 Go, même si vous avez mis 16 Go auparavant via T‑SQL.
  • Installer/upgrade : certains processus d’installation peuvent proposer/poser une « recommandation » (≈ 75 % de la RAM détectée). Sur un hôte à 32 Go, cela peut retomber à ~24 Go si un script d’installation est rejoué.
  • Clustering ou bascule : en Always On/FCI, selon l’architecture, chaque nœud peut porter sa propre valeur. Une bascule sur un nœud non aligné peut donner 24 Go.
  • Conteneurs/Linux : en environnement Linux ou container, la limite est notamment pilotée par mssql.conf (voir plus bas). Un redéploiement peut remettre l’ancien fichier.

Comprendre où et comment SQL Server persiste « max server memory »

Windows (instance SQL Server 2019)

  • La valeur logique est visible dans sys.configurations.
  • La valeur persistée est stockée dans le Registre :
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\<InstanceID>\MSSQLServer, nom de valeur Max Server Memory (en Mo).
    Exemple d’InstanceID pour l’instance par défaut SQL 2019 : MSSQL15.MSSQLSERVER.

Linux (SQL Server 2019)

  • Paramétrage via /var/opt/mssql/mssql.conf : [memory] memorylimitmb = 16384
  • Commande équivalente : sudo /opt/mssql/bin/mssql-conf set memory.memorylimitmb 16384 sudo systemctl restart mssql-server

Scripts de diagnostic : confirmer ce qui est réellement en vigueur

Lecture de la configuration serveur

SELECT name, value, value_in_use, description
FROM sys.configurations
WHERE name IN ('min server memory (MB)', 'max server memory (MB)');

Informations mémoire côté OS et processus SQL

SELECT total_physical_memory_kb, available_physical_memory_kb, system_memory_state_desc
FROM sys.dm_os_sys_memory;

SELECT physical_memory_in_use_kb, large_page_allocations_kb, locked_page_allocations_kb,
process_physical_memory_low, process_virtual_memory_low
FROM sys.dm_os_process_memory;

Compteurs clés PerfMon (via DMV)

SELECT counter_name, cntr_value
FROM sys.dm_os_performance_counters
WHERE object_name LIKE '%Memory Manager%'
  AND counter_name IN ('Total Server Memory (KB)', 'Target Server Memory (KB)', 'Memory Grants Pending');

Appliquer et verrouiller la bonne valeur

Avec T‑SQL (immédiat)

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'max server memory (MB)', 16384; -- 16 Go
RECONFIGURE;

Cette modification prend effet sans redémarrage. Un redémarrage reste recommandé pour vérifier la persistance (et déceler un éventuel « écrasement » à l’amorçage).

Assainir le Registre (Windows)

Si le Registre contient 24576 Mo, SQL Server reviendra à 24 Go au prochain démarrage. Mettez la clé en conformité :

# Adapter l'InstanceID et la valeur selon votre cas
$inst = 'MSSQL15.MSSQLSERVER' # Instance par défaut SQL 2019
$path = "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$inst\MSSQLServer"
Set-ItemProperty -Path $path -Name 'Max Server Memory' -Value 16384 -Type DWord
Restart-Service -Name 'MSSQLSERVER' -Force

Pour une instance nommée : service MSSQL$NomInstance et InstanceID typiquement MSSQL15.NOMINSTANCE.

Identifier ce qui ré‑applique 24 Go : check‑list d’investigation

1) Jobs SQL Agent, tâches planifiées, scripts de démarrage

Jobs SQL Agent qui appellent sp_configure :

SELECT j.name AS job_name, s.step_id, s.subsystem, s.command
FROM msdb.dbo.sysjobsteps AS s
JOIN msdb.dbo.sysjobs     AS j ON j.job_id = s.job_id
WHERE s.command LIKE '%sp_configure%'
  AND s.command LIKE '%max server memory%';

Procédures de démarrage (automatiques) :

SELECT p.name, p.create_date, p.modify_date
FROM sys.procedures AS p
WHERE OBJECTPROPERTY(p.object_id, 'ExecIsStartup') = 1;

-- Voir le code si nécessaire
SELECT OBJECT_SCHEMA_NAME(object_id) AS schema_name, name, OBJECT_DEFINITION(object_id) AS code
FROM sys.procedures
WHERE OBJECTPROPERTY(object_id, 'ExecIsStartup') = 1;

Déclencheurs DDL serveur susceptibles de modifier la config :

SELECT name, is_disabled, create_date, modify_date
FROM sys.server_triggers;

SELECT name, OBJECT_DEFINITION(object_id) AS trigger_body
FROM sys.server_triggers;

Tâches planifiées Windows et scripts PowerShell :

Get-ScheduledTask |
  Where-Object { $_.Actions -match 'sp_configure|mssql-conf|Set-ItemProperty' } |
  Format-Table TaskName, State, LastRunTime, Actions -Auto

2) PBM (Policy‑Based Management) et conformité

Un DBA peut avoir déployé une politique qui « répare » la configuration au démarrage.

SELECT p.name AS policy_name, p.is_enabled, c.name AS condition_name
FROM msdb.dbo.syspolicy_policies   AS p
JOIN msdb.dbo.syspolicy_conditions AS c ON p.condition_id = c.condition_id
WHERE c.name LIKE '%memory%' OR c.facet LIKE '%Server%';

3) Trace par défaut / journal SQL Server : qui a changé quoi ?

Les changements de configuration laissent des traces. Deux pistes utiles :

  • Journal SQL Server : lignes « Configuration option ‘max server memory (MB)’ changed from … »
  • Trace par défaut : évènement « Audit Server Altered », utile pour retrouver login/hôte
-- Journal SQL Server
EXEC xp_readerrorlog 0, 1, 'max server memory';

-- Trace par défaut : retrouver les changements relatifs à max server memory
DECLARE @tf NVARCHAR(4000);
SELECT @tf = CONVERT(nvarchar(4000), value)
FROM ::fn_trace_getinfo(DEFAULT)
WHERE property = 2;

SELECT 
  TE.name        AS event_name,
  T.StartTime,
  T.LoginName, T.HostName, T.ApplicationName,
  T.TextData
FROM ::fn_trace_gettable(@tf, DEFAULT) AS T
JOIN sys.trace_events AS TE
  ON TE.trace_event_id = T.EventClass
WHERE TE.name IN ('Audit Server Altered','ErrorLog')
  AND T.TextData LIKE '%max server memory%'

4) Clustering/Always On : cohérence inter‑nœuds

  • AG (Availability Groups) : chaque instance est indépendante ; alignez max server memory sur chaque nœud hébergeant un replica qui peut devenir primaire.
  • FCI (Failover Cluster Instance) : vérifiez la cohérence de la valeur au niveau des registres et paramètres propres au cluster/instance.

5) Linux & conteneurs

  • Vérifiez /var/opt/mssql/mssql.conf (memorylimitmb) et la commande de lancement du container (limites mémoire Docker/Kubernetes). Un redeploy peut réinjecter une ancienne valeur.

Mesures préventives : auditer et alerter la dérive de configuration

Option A : Extended Events ciblé (léger et précis)

CREATE EVENT SESSION [TrackConfigMemory] ON SERVER 
ADD EVENT sqlserver.errorlog_written(
    WHERE message LIKE '%max server memory%'),
ADD EVENT sqlserver.sql_batch_completed(
    ACTION(sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.sql_text, sqlserver.username)
    WHERE sql_text LIKE '%sp_configure%' AND sql_text LIKE '%max server memory%'),
ADD EVENT sqlserver.rpc_completed(
    ACTION(sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.username, sqlserver.statement)
    WHERE statement LIKE '%sp_configure%' AND statement LIKE '%max server memory%')
ADD TARGET package0.event_file (SET filename = N'C:\XE\TrackConfigMemory.xel');
GO
ALTER EVENT SESSION [TrackConfigMemory] ON SERVER STATE = START;

Vous capturez uniquement ce qui touche max server memory, avec le minimum de bruit.

Option B : Job d’alerte en cas de dérive

Un job quotidien (ou à chaque démarrage) qui notifie si la valeur s’éloigne de 16384 Mo :

IF EXISTS (
  SELECT 1
  FROM sys.configurations
  WHERE name = 'max server memory (MB)'
    AND value_in_use <> 16384
)
BEGIN
    -- Exemple : écriture dans un journal d'audit applicatif
    PRINT 'ALERTE: max server memory ne vaut pas 16384 Mo';
    -- À adapter: envoi mail via Database Mail, etc.
END;

Option C : Procédure de démarrage (solution de contournement)

Si vous n’avez pas la main sur l’automatisation amont, une procédure de démarrage peut réimposer la valeur souhaitée. À n’utiliser que si vous maîtrisez l’instance et que le changement est approuvé :

CREATE OR ALTER PROCEDURE dbo.EnforceMaxMemory
AS
BEGIN
    -- Réapplique 16 Go au démarrage
    EXEC sp_configure 'show advanced options', 1;
    RECONFIGURE;
    EXEC sp_configure 'max server memory (MB)', 16384;
    RECONFIGURE WITH OVERRIDE;
END
GO
EXEC sys.sp_procoption @ProcName = 'dbo.EnforceMaxMemory', @OptionName = 'startup', @OptionValue = 'on';

Note : cette approche masque la cause racine. Préférez corriger la source (GPO/DSC, scripts, etc.).

Bonnes pratiques de dimensionnement

Fixer « au hasard » 16 Go n’est pas toujours optimal. Basez‑vous sur un calcul simple :

ÉlémentRecommandation typiqueCommentaires
Réserve OS2 à 4 Go (serveur ≤ 32 Go)Plus si antivirus, outils de sauvegarde, monitoring, etc.
Services annexes SQL0,5 à 2 GoSSIS, SSRS, connecteurs, drivers, etc.
Max server memoryRAM totale – Réserves ci‑dessusAjuster selon charge OLTP/OLAP, bdd concurrentes, croissance prévue.
Min server memory2–6 Go sous la valeur de maxStabilise l’empreinte mémoire, évite les variations agressives.

Exemple : hôte 32 Go, OS 3 Go, services annexes 1 Go → max server memory ≈ 28 Go. Vous pouvez néanmoins choisir 16 Go pour ménager d’autres applications ou VMs ; documentez cette décision.

Vérifications post‑changement

  1. Confirmez value_in_use : SELECT name, value_in_use FROM sys.configurations WHERE name = 'max server memory (MB)';
  2. Redémarrez le service et revérifiez (si possible hors heures de pointe).
  3. Surveillez les indicateurs pendant quelques jours :
    • Target Server Memory vs Total Server Memory : doit converger.
    • Memory Grants Pending : idéalement 0 de façon stable.
    • Page Life Expectancy : à interpréter par instance/NUMA ; ne pas absolutiser.

Cas particuliers & pièges fréquents

  • « min » > « max » : évitez cette incohérence (valeurs contradictoires, comportements inattendus).
  • Lock Pages In Memory (LPIM) : améliore la stabilité des allocations mais n’explique pas à lui seul un reset de la valeur. Ce n’est pas la cause du retour à 24 Go.
  • VMs avec mémoire dynamique : l’allocation hôte invitée n’influe pas directement sur max server memory, mais des scripts d’exploitation peuvent ajuster la config lors des changements de capacité.
  • Mises à jour/patchs : certains pipelines de patching rejouent des scripts d’installation « standards ». Vérifiez votre référentiel d’automatisation.
  • Multi‑instances : additionnez les max server memory des instances d’un même hôte et laissez une réserve suffisante à l’OS.

FAQ rapide

Q : Puis‑je laisser une valeur un peu supérieure (ex. 20 Go au lieu de 16 Go) ?
R : Oui, SQL Server alloue progressivement jusqu’à la limite. Une légère marge n’entraîne pas de dépassement immédiat, mais dimensionnez en connaissance de cause.

Q : Pourquoi 24 Go précisément ?
R : C’est souvent une valeur « recommandée » par certains scripts/assistants (par ex. ~75 % d’un hôte 32 Go) appliquée automatiquement à l’installation ou au redémarrage.

Q : Dois‑je redémarrer après sp_configure ?
R : Pas nécessaire pour la prise d’effet. Utile pour vérifier que rien ne réécrit la valeur à l’amorçage.

Checklist express de remédiation

  1. Exécutez les requêtes de diagnostic (sys.configurations, DMVs, compteurs).
  2. Fixez 16 Go via sp_configure et alignez le Registre ou mssql.conf.
  3. Inspectez jobs, procédures de démarrage, déclencheurs DDL, PBM, GPO/DSC.
  4. Vérifiez clusters/AG : alignement inter‑nœuds.
  5. Ajoutez une surveillance (XE/alerte) pour prévenir toute dérive future.

Référence rapide : commandes utiles

ObjectifCommande
Afficher max/min server memorySELECT name, value, value_in_use FROM sys.configurations WHERE name LIKE '%server memory%';
Fixer max à 16 GoEXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'max server memory (MB)', 16384; RECONFIGURE;
Lire les changements dans le journalEXEC xp_readerrorlog 0, 1, 'max server memory';
Trouver un job SQL Agent suspectSELECT j.name, s.step_id, s.command FROM msdb.dbo.sysjobsteps s JOIN msdb.dbo.sysjobs j ON j.job_id = s.job_id WHERE s.command LIKE '%max server memory%';
Procédures de démarrageSELECT name FROM sys.procedures WHERE OBJECTPROPERTY(object_id, 'ExecIsStartup') = 1;
Déclencheurs DDL serveurSELECT name, is_disabled FROM sys.server_triggers;
Linux : fixer la limitesudo /opt/mssql/bin/mssql-conf set memory.memorylimitmb 16384 sudo systemctl restart mssql-server
Windows : fixer via PowerShell$inst = 'MSSQL15.MSSQLSERVER' $path = "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$inst\MSSQLServer" Set-ItemProperty -Path $path -Name 'Max Server Memory' -Value 16384 -Type DWord Restart-Service MSSQLSERVER

Conclusion

Un retour systématique à 24 Go indique presque toujours une automatisation ou une incohérence de persistance (Registre / fichier de configuration) qui écrase votre paramètre. En combinant : vérification T‑SQL, correction de la valeur persistée, recherche des mécanismes de réapplication (jobs, PBM, GPO/DSC, déclencheurs, procédures de démarrage) et surveillance proactive (XE/alerte), vous fixerez durablement max server memory à 16 Go et garantirez la stabilité de votre instance SQL Server 2019.

Informations complémentaires utiles

  • Valeur « recommandée » à l’installation : certains assistants ou scripts de déploiement déterminent une valeur ≈ 75 % de la RAM (ex. 24 Go pour 32 Go), ce qui peut expliquer un retour à 24 Go si ces scripts se rejouent.
  • Mémoire dynamique : même avec un max server memory défini, SQL Server augmente ses allocations jusqu’à la limite. Une légère surévaluation ne casse pas l’instance, mais mieux vaut dimensionner proprement.
  • Audit : journalisez tout changement (scripts, dépôt Git, Change Log) et documentez vos pipelines d’automatisation pour accélérer les diagnostics lors de futures anomalies.
Sommaire