Status: Reviewed
Stack: PowerShell → SQL / stored procs → Blazor
Depends on: SQL-CLI-09 (overview), SQL-CLI-01 (calling)
Goal: Deep practical use of sp_configure / RECONFIGURE and related instance helpers from CLI scripts — with DMV/catalog read paths for Blazor inventory.
Sources: Microsoft Learn (sql-server-ver17 / 2026). Expands SQL-CLI-09 §3.1 only — do not treat this as a rewrite of the overview. Patterns for staging → Blazor: SQL-CLI-07.
| In this doc (09a) | Out → sibling |
|---|---|
sp_configure + RECONFIGURE / WITH OVERRIDE |
Object help (sp_help*, sp_rename, space) → 09b |
sys.configurations inventory / pending vs running |
Security / principals / orphans → 09c |
sp_helpserver, sp_who / sp_who2, thin instance helpers |
Agent job control → 09d |
| Permissions for ALTER SETTINGS; change logging | Surface area / xp_* deep dive → 09e |
| High-value option table + CLI recipes | Full option encyclopedia → Learn Server configuration options |
Write path stays sp_configure + RECONFIGURE.
Read path for Blazor is always sys.configurations (and friends) — never scrape sp_configure text output into a grid.
Database-scoped knobs (MAXDOP, etc.) are ALTER DATABASE SCOPED CONFIGURATION, not this doc. Soft-NUMA / some affinity paths may also use ALTER SERVER CONFIGURATION.
sp_configure deep divesp_configure 'option', N → writes pending value (config_value / sys.configurations.value)
RECONFIGURE [WITH OVERRIDE] → installs running value when dynamic (run_value / value_in_use)
is_dynamic = 0 → still needs service restart after RECONFIGURE
Column (sp_configure) |
Catalog (sys.configurations) |
Meaning |
|---|---|---|
config_value |
value |
What you asked for (pending or installed) |
run_value |
value_in_use |
What the engine is actually using |
| — | is_dynamic |
1 = takes effect on RECONFIGURE; 0 = restart required |
| — | is_advanced |
Hidden until show advanced options = 1 |
Partial name match: Engine accepts any unique substring of the option name. Prefer the full name in scripts ('max degree of parallelism', not 'max degree' unless you own uniqueness forever).
Advanced options (affinity, MAXDOP, recovery interval, surface-area XPs, …) are invisible until:
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- … do work …
EXEC sp_configure 'show advanced options', 0;
RECONFIGURE;
Ops rule: leave advanced off in steady state. Leaving it on is not a security boundary (any user who can run sp_configure with one arg already sees names once it’s on), but it is noise and a tell that someone left a change window open. The setting is global — not session-scoped.
RECONFIGURE vs RECONFIGURE WITH OVERRIDERECONFIGURE |
RECONFIGURE WITH OVERRIDE |
|
|---|---|---|
| Sanity / “nonrecommended” checks | Yes (e.g. recovery interval > 60 min rejected) | Skips those checks |
| Type / hard fatal conflicts | Still blocked | Still blocked (e.g. min memory > max memory) |
| When Rick uses it | Default for every change | Rare: documented override cases, or recovering a boxed-in setting |
| Risk | Low if value is in published range | Can install stupid values that hurt the instance |
RECONFIGURE is not allowed inside an explicit/implicit transaction. Batch several sp_configure calls, then one RECONFIGURE — if any part fails validation, none of the pending installs apply.
Changes are written to the SQL Server error log.
is_dynamic = 0)After RECONFIGURE, if value <> value_in_use and is_dynamic = 0, schedule a controlled restart. There is no catalog flag that proves “RECONFIGURE already ran for this non-dynamic option” — so always RECONFIGURE before restart so the pending value is staged.
Common RR options Rick may actually touch: fill factor (%), tempdb metadata memory-optimized, scan for startup procs, user connections, remote access, lightweight pooling, priority boost (don’t), affinity I/O masks, c2 audit mode / common criteria, hardware-offload / enclave options on newer builds.
Defaults and restart flags from Learn Server configuration options (sql-server-ver17). “Default spirit” = what a fresh / typical install implies, not every edition nuance.
| Option | Default spirit | When Rick touches it | Restart? | Risk |
|---|---|---|---|---|
| show advanced options | 0 — advanced hidden |
Gate before reading/setting advanced; flip back to 0 |
No | Low — leave on = messy; not a real ACL |
| max degree of parallelism | 0 = all schedulers (often wrong on big boxes) |
Cap parallelism (NUMA / OLTP); align with MS MAXDOP guidance; prefer DB-scoped where needed | No (advanced) | Medium — too high = CXPACKET/threadpool; too low = serial CPU burn |
| cost threshold for parallelism | 5 (ancient; too eager) |
Raise (often 25–50+) so cheap OLTP stays serial | No (advanced) | Low–medium — wrong value skews plan shape |
| max server memory (MB) | ~unlimited (2147483647) |
Cap so OS / other instances breathe; leave headroom | No (advanced, self-configuring) | High if too low (stolen pages / pressure); high if left unlimited on shared hosts |
| min server memory (MB) | 0 (engine picks floor) |
Rarely — pin floor on multi-instance hosts | No (advanced) | Medium — starving other apps if too high |
| backup compression default | 0 off |
1 for fleet-wide smaller/faster backups (CPU trade) |
No | Low — CPU cost; check TDE/already-compressed edge cases |
| backup compression algorithm | 0 (2022+; max rises in 2025) |
Pick algorithm when policy cares (MSZIP vs newer) | No | Low — know restore-side version compatibility |
| backup checksum default | 0 off |
1 for safer backups / restore validation culture |
No | Low — slight backup CPU |
| remote admin connections | 0 |
1 to allow remote DAC when the instance is wedged |
No | Medium — expose DAC only on admin networks; still need connectivity |
| optimize for ad hoc workloads | 0 |
1 on high-ad-hoc / ORM-ish workloads to shrink single-use plan cache bloat |
No (advanced) | Low — good default on many app servers |
| blocked process threshold (s) | 0 off |
Set (≥5) to emit blocked-process reports for monitoring | No (advanced) | Low — noise if too aggressive |
| recovery interval (min) | 0 = self-configuring (~1 min target) |
Almost never; leave alone unless checkpoint strategy is deliberate | No (advanced, SC) | High if raised carelessly; >60 often needs WITH OVERRIDE |
| remote query timeout (s) | 600 |
Tune linked-server / remote query patience | No | Medium — hide real hangs vs kill slow ETL |
| contained database authentication | 0 |
1 only when adopting contained DBs |
No | Medium — expands auth surface; policy decision |
| Database Mail XPs | 0 |
1 when enabling Database Mail |
No (advanced) | Medium — mail = phishing/spam surface if misconfigured |
| Agent XPs | 0 until Agent starts (then often 1) |
Don’t fight Agent; ensure Agent service policy is intentional | No (advanced) | Low — tied to Agent lifecycle |
| clr enabled | 0 |
Only if CLR assemblies are approved | No | High — code execution in-engine; pair with clr strict security |
| Ole Automation Procedures | 0 |
Prefer never; legacy COM from T-SQL | No (advanced) | High — surface area; see 09e |
| xp_cmdshell | 0 |
Mention only — do not enable from habit. Deep rules → 09e | No (advanced) | Critical — OS shell from SQL |
| fill factor (%) | 0 = engine default 100% for new indexes |
Rare global default; prefer per-index FILLFACTOR | Yes (advanced) | Medium — wrong global default wastes space forever |
| tempdb metadata memory-optimized | 0 |
Consider on 2019+ under heavy tempdb metadata contention | Yes (advanced) | Medium — memory + restart; test first |
| scan for startup procs | 0 |
1 only with audited sp_procoption startup procs |
Yes (advanced) | High — silent code at every start |
Also note (inventory, rarely set by hand): priority boost (RR — leave 0), lightweight pooling (RR — almost never), affinity I/O masks (RR — NUMA specialists only).
SQL Server 2025 (17.x) watchlist (appear in Learn option list; confirm on your build before scripting): allow server scoped db credentials, availability group commit time (ms), external rest endpoint enabled, max ucs send boxcars, max lock manager cache memory (%) (RR, CU-gated). Treat as “inventory + ticket,” not casual toggles.
SELECT
@@SERVERNAME AS instance_name,
c.configuration_id,
c.name,
CAST(c.value AS bigint) AS config_value,
CAST(c.value_in_use AS bigint) AS value_in_use,
CAST(c.minimum AS bigint) AS minimum_value,
CAST(c.maximum AS bigint) AS maximum_value,
c.is_dynamic,
c.is_advanced,
c.description,
CASE
WHEN CAST(c.value AS bigint) <> CAST(c.value_in_use AS bigint) THEN 1
ELSE 0
END AS is_pending_or_mismatch,
CASE
WHEN c.is_dynamic = 0
AND CAST(c.value AS bigint) <> CAST(c.value_in_use AS bigint)
THEN 1 ELSE 0
END AS needs_restart,
SYSUTCDATETIME() AS collected_utc
FROM sys.configurations AS c;
Permissions: historically public. On SQL Server 2022+, Learn documents VIEW SERVER PERFORMANCE STATE for sys.configurations — grant that (or broader VIEW SERVER STATE) to the inventory login. Do not assume anonymous public works on locked-down 2022/2025 builds.
| Situation | Action |
|---|---|
value <> value_in_use and is_dynamic = 1 |
Someone forgot RECONFIGURE, or it failed |
value <> value_in_use and is_dynamic = 0 |
Restart still owed (after a successful RECONFIGURE) |
max server memory default 0 vs value_in_use huge |
Expected display quirk on some builds — don’t alert blindly |
min server memory 0 vs small value_in_use |
Expected floor behavior |
Filter “real” pending for alerts:
SELECT name, value, value_in_use, is_dynamic
FROM sys.configurations
WHERE value <> value_in_use
AND name NOT IN (N'max server memory (MB)', N'min server memory (MB)');
Prefer one result set from sys.configurations, not EXEC sp_configure.
Staging table sketch (inventory DB):
CREATE TABLE dbo.SqlInstanceConfig (
SnapshotId bigint NOT NULL, -- FK to collection run
InstanceName nvarchar(128) NOT NULL,
ConfigurationId int NOT NULL,
OptionName nvarchar(35) NOT NULL,
ConfigValue bigint NULL,
ValueInUse bigint NULL,
MinimumValue bigint NULL,
MaximumValue bigint NULL,
IsDynamic bit NOT NULL,
IsAdvanced bit NOT NULL,
Description nvarchar(255) NULL,
IsPendingOrMismatch bit NOT NULL,
NeedsRestart bit NOT NULL,
CollectedUtc datetime2(3) NOT NULL,
CONSTRAINT PK_SqlInstanceConfig PRIMARY KEY (SnapshotId, ConfigurationId)
);
Blazor grid: filter NeedsRestart = 1, IsPendingOrMismatch = 1, or “surface area” name list (xp_cmdshell, Ole Automation Procedures, clr enabled, Ad Hoc Distributed Queries, …).
sqlcmd CSV:
sqlcmd -S "$srv" -E -d master -b -s"," -W -Q "SET NOCOUNT ON; SELECT ..." -o config.csv
Invoke-Sqlcmd → objects:
$rows = Invoke-Sqlcmd -ServerInstance $srv -Database master -Query $q
$rows | Export-Csv .\config.csv -NoTypeInformation
# or ConvertTo-Json for Blazor API staging — see SQL-CLI-07
Be honest: outside sp_configure, the “instance helper” shelf is thin. Prefer catalog/DMVs for anything that feeds Blazor.
| Helper | What it does | When OK | Prefer instead |
|---|---|---|---|
sp_helpserver |
Linked/remote/replication server summary (name, network, status, collation, timeouts) | Interactive peek | sys.servers, sys.linked_logins |
sp_who |
Documented session list; @loginame = login / SPID / ACTIVE |
Quick triage in sqlcmd | sys.dm_exec_sessions + requests + connections |
sp_who2 |
Undocumented richer who (CPU, IO, BlkBy, Program) | Human eyeballs only | Same DMVs; interactive: community sp_WhoIsActive |
sp_monitor |
Cumulative busy/idle/IO/packet/error/connection deltas since last call | Rare curiosity | Perf DMVs / ring buffers / monitoring stack |
sp_server_info |
ODBC attribute dump (DBMS_VER, name lengths, …) |
Driver/compat debugging | SERVERPROPERTY, sys.dm_os_sys_info |
sp_who / sp_who2 rules for this stack
EXEC sp_who2 'ACTIVE'.sp_who2 is undocumented).#t + filter is a smell — write the DMV query once instead.sp_helpserver: useful confirmation that a linked server exists; scripting should still land on sys.servers.
sp_monitor: stateful between calls (shows deltas). Not a substitute for baseline monitoring. Requires elevated permission historically (sysadmin / explicit EXECUTE).
sp_server_info: public; ODBC-oriented. Don’t build config dashboards on it.
| Action | Permission |
|---|---|
sp_configure with no args or name only (read) |
Granted to public by default |
sp_configure with name + value (write) |
ALTER SETTINGS |
RECONFIGURE / WITH OVERRIDE |
ALTER SETTINGS |
| ALTER SETTINGS holders (implicit) | sysadmin, serveradmin |
Read sys.configurations (2022+) |
VIEW SERVER PERFORMANCE STATE (per Learn) — plan grants for inventory logins |
| Session/blocking DMVs | VIEW SERVER STATE / PERFORMANCE STATE family |
Least privilege for Blazor inventory: login with VIEW SERVER PERFORMANCE STATE (and whatever else your collector needs) — not serveradmin.
Config change jobs: dedicated admin principal; never the Blazor app pool.
| Signal | Notes |
|---|---|
| SQL Server error log | sp_configure / RECONFIGURE activity is logged — scrape with xp_readerrorlog or your log shipper |
| Default trace / system_health | May capture some DDL-ish noise; do not rely as sole audit |
| SQL Audit / XE | Best practice: Audit group covering server configuration / successful/failed permission checks for ALTER SETTINGS holders |
| Your change ticket | Script + before/after sys.configurations snapshot in the PR / runbook |
Recipe mindset: before change → snapshot table; after → snapshot; diff config_value / value_in_use.
RECONFIGURE — config_value moves; nothing runs differently. Always verify value_in_use.WITH OVERRIDE as habit — hides mistakes (recovery interval, conflicting masks).show advanced options = 1 — noisy; reset when done.value <> value_in_use as always urgent — exclude known memory display quirks.value_in_use.sp_configure / sp_who2 into Blazor — multi-set / undocumented. Use catalog + DMVs.xp_cmdshell, Ole Automation, Ad Hoc Distributed Queries, clr without review → 09e.priority boost = 1 — classic foot-gun; leave off.sp_configure instance knobs don’t apply the same way; this doc targets SQL Server / MI-class instances.EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure;
EXEC sp_configure 'show advanced options', 0;
RECONFIGURE;
SELECT name,
CAST(value AS bigint) AS config_value,
CAST(value_in_use AS bigint) AS value_in_use,
is_dynamic
FROM sys.configurations
WHERE value <> value_in_use
ORDER BY is_dynamic, name;
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'max degree of parallelism', 4; -- example only
EXEC sp_configure 'cost threshold for parallelism', 50; -- example only
RECONFIGURE;
EXEC sp_configure 'show advanced options', 0;
RECONFIGURE;
SELECT name, value, value_in_use
FROM sys.configurations
WHERE name IN (N'max degree of parallelism', N'cost threshold for parallelism');
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'max server memory (MB)', 65536; -- example: 64 GB
RECONFIGURE;
EXEC sp_configure 'show advanced options', 0;
RECONFIGURE;
EXEC sp_configure 'backup compression default', 1;
EXEC sp_configure 'backup checksum default', 1;
RECONFIGURE;
EXEC sp_configure 'remote admin connections', 1;
RECONFIGURE;
sqlcmd -S "$SQL_SERVER" -E -d master -b -s"," -W \
-Q "SET NOCOUNT ON;
SELECT @@SERVERNAME AS instance_name, name,
CAST(value AS bigint) AS config_value,
CAST(value_in_use AS bigint) AS value_in_use,
is_dynamic, is_advanced,
CASE WHEN value <> value_in_use THEN 1 ELSE 0 END AS is_pending
FROM sys.configurations ORDER BY name;" \
-o "./SqlConfig_${SQL_SERVER}.csv"
$q = @"
SET NOCOUNT ON;
SELECT @@SERVERNAME AS InstanceName, configuration_id AS ConfigurationId,
name AS OptionName, CAST(value AS bigint) AS ConfigValue,
CAST(value_in_use AS bigint) AS ValueInUse, is_dynamic AS IsDynamic,
is_advanced AS IsAdvanced,
CASE WHEN value <> value_in_use THEN 1 ELSE 0 END AS IsPendingOrMismatch,
CASE WHEN is_dynamic = 0 AND value <> value_in_use THEN 1 ELSE 0 END AS NeedsRestart,
SYSUTCDATETIME() AS CollectedUtc
FROM sys.configurations;
"@
$rows = Invoke-Sqlcmd -ServerInstance $env:SQL_SERVER -Database master -Query $q -TrustServerCertificate
$rows | ConvertTo-Json -Depth 3 | Set-Content -Path ".\config-$($env:SQL_SERVER).json" -Encoding UTF8
function Get-SqlConfigSnapshot([string]$Server) {
Invoke-Sqlcmd -ServerInstance $Server -Database master -TrustServerCertificate -Query @"
SELECT name, CAST(value AS bigint) AS v, CAST(value_in_use AS bigint) AS u, is_dynamic
FROM sys.configurations;"
}
$before = Get-SqlConfigSnapshot $srv
# ... run change script with -b / check exit code (SQL-CLI-01) ...
$after = Get-SqlConfigSnapshot $srv
Compare-Object $before $after -Property name,v,u,is_dynamic | Format-Table
sqlcmd -S "$SQL_SERVER" -E -d master -Q "EXEC sp_who2 'ACTIVE';"
# Automation / Blazor: use DMVs instead — see SQL-CLI-09 §2
| Doc | Covers |
|---|---|
| SQL-CLI-09 | Overview: call patterns, procs vs DMVs, full curated catalog |
| 09b (objects) | sp_help* / sp_spaceused / sp_rename — and catalog replacements |
| 09c (security) | Logins/users/roles helpers; deprecated sp_change_users_login; modern DDL |
| 09d (Agent) | msdb job help/start/history/update — control plane vs dashboard tables |
09e (surface / xp_*) |
xp_cmdshell, Ole Automation, related XPs — enablement policy & safer alternatives |
Related stack docs: SQL-CLI-01 (calling), SQL-CLI-07 (Collect→Stage→Blazor).
Learn anchors (ver17): sp_configure, RECONFIGURE, sys.configurations, Server configuration options, sp_helpserver, sp_who, sp_monitor, sp_server_info.