Instance SQL Server obsahují databáze obsahující data pro back-endový zásobník obchodního modelu nebo konfigurační data pro konkrétní aplikace. Bez ohledu na případ použití má instance sadu hodnot/nastavení, které by měly být vyladěny tak, aby dodržovaly osvědčené postupy.
Účelem uložené procedury, kterou v tomto článku představuji, je představit DBA sadu důležitých nastavení/hodnot, které by neměly být přehlíženy. Kromě toho se podělím o skvělou funkci, která pomáhá správcům databází udržet kontrolu nad jakýmkoli konkrétním nastavením/hodnotou, která byla nedávno změněna/upravena.
Počáteční úvahy
Ujistěte se, že účet, který použijete ke spuštění této uložené procedury, má dostatečná oprávnění. Vím, že žádat o uživatele s oprávněním sysadmin zní jako příliš mnoho, ale je to nejjednodušší způsob, jak to správně spustit, protože SP používá xp_cmdshell a další speciální systémové uložené procedury pro provedení práce. Nebo můžete vyladit uživatelská práva tak, aby dodržovala zásadu nejmenších oprávnění.
Jak používat uloženou proceduru SQL?
- Zkopírujte a vložte kód SP TSQL uvedený v tomto článku.
- SP očekává pouze 1 parametr:@ storeValuesInTable
Ano je, pokud si DBA přeje uložit výstup do cílové tabulky, a N je, pokud DBA chce pouze přímo vidět výstup.
Prezentovaná pole a jejich význam
- verze_sql – aktuální verzi instance serveru SQL.
- sql_edition – aktuální verzi SQL Server instance.
- číslo_sestavení – aktuální číslo sestavení instance.
- min_server_memory – aktuální hodnota (v MB) přiřazená k Min. paměti serveru.
- max_server_memory – aktuální hodnota (v MB) přiřazená paměti Max serveru.
- server_memory – aktuální hodnotu (v MB), kterou má server hostující instanci SQL Server k dispozici.
- jádra_serveru – množství jader vCPU, které má server hostující instanci SQL Server.
- sql_cores – množství jader vCPU, které instance SQL Server přiřadila ke svému použití.
- cost_threshold_for_parallelism – aktuální hodnotu přiřazenou k nastavení Cost Threshold for Parallelism.
- max_degree_of_parallelism – aktuální hodnotu přiřazenou k nastavení Maximální stupeň rovnoběžnosti.
- lpim_enabled – 0, pokud Zamknout stránky v paměti nastavení je zakázáno a 1, pokud je povoleno.
- ifi_enabled – 0, pokud je inicializace okamžitého souboru je zakázáno a 1, pokud je povoleno.
- installed_date – datum a čas instalace instance SQL Server.
- sql_service_account – servisní účet, který bude spouštět službu DB Engine.
- sql_agent_service_account – účet služby, který bude spouštět službu Agent.
- čas_spouštění – hodnota data a času, kdy byla instance SQL Server nedávno spuštěna.
- data_collection_timestamp – viditelné pouze pokud Y se předává SP. Používá se k definování, kdy byl SP proveden a úspěšně uloženy informace v InstanceValues stůl.
Testy provedení uložené procedury v SQL
Předvedu několik provedení uložené procedury, abyste získali představu, co od ní očekávat.
EXEC DBA_InstanceValues @storeValuesInTable = 'N'
EXEC DBA_InstanceValues @storeValuesInTable = 'Y'
Pro toto konkrétní provedení bude výstup uložen do tabulky nazvané InstanceValues . Pokud neexistuje, bude vytvořen v cílové databázi.
Tabulka má téměř stejnou strukturu jako na obrázku výše, s malým rozdílem:obsahuje pole nazvané data_collection_timestamp na samém konci tabulky.
The data_collection_timestamp pole je užitečné pro několik účelů:
- abychom vám řekli, kdy byl SP proveden ke sběru uložených dat (zcela zřejmé).
- Chcete-li hledat rozdíly v určitém časovém rozmezí pro jakékoli konkrétní pole nastavení.
Abych dokázal, že je to užitečné, dovolte mi uvést rychlý příklad.
Jednou jsem provedl SP a předal jsem Y parametr. Příslušný záznam byl vložen do InstanceValues stůl. Poté změním cost_threshold_for_parallelism hodnotu v rámci mé instance na 50 a poté spusťte skript znovu.
Jak můžete vidět, úprava byla úspěšně zaprotokolována do InstanceValues stůl. Jak to může být užitečné?
Pokud vytvoříte úlohu agenta, která provádí tuto uloženou proceduru denně, můžete vytvořit mechanismus interního auditu sledovat, kdy se konkrétní hodnota nastavení změní, jak jsem předvedl. Můžete si tak ponechat plnou kontrolu nad instancí SQL Server. Pokud se mě ptáte, je to něco extrémně užitečného.
Úplný kód uložené procedury
Na samém začátku skriptu uvidíte výchozí hodnotu. Uložená procedura ji předpokládá, pokud parametru není předána žádná hodnota.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author : Alejandro Cobar
-- Create date: 2021-05-15
-- Description: SP to retrieve important instance settings/values
-- =============================================
CREATE PROCEDURE [dbo].[DBA_InstanceValues]
@storeValuesInTable CHAR(1) = 'N'
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sqlCommand VARCHAR(4096)
SET @sqlCommand = ''
IF(@storeValuesInTable = 'Y')
BEGIN
IF NOT EXISTS (SELECT * FROM dbo.sysobjects where id = object_id(N'[InstanceValues]') and OBJECTPROPERTY(id, N'IsTable') = 1)
BEGIN
CREATE TABLE InstanceValues(
[sql_version] [VARCHAR](32) NOT NULL,
[sql_edition] [VARCHAR](64) NOT NULL,
[build_number] [VARCHAR](32) NOT NULL,
[min_server_memory] [DECIMAL](15,2) NOT NULL,
[max_server_memory] [DECIMAL](15,2) NOT NULL,
[server_memory] [DECIMAL](15,2) NOT NULL,
[server_cores] [SMALLINT] NOT NULL,
[sql_cores] [SMALLINT] NOT NULL,
[cost_threshold_for_parallelism][SMALLINT] NOT NULL,
[max_degree_of_parallelism] [SMALLINT] NOT NULL,
[lpim_enabled] [TINYINT] NOT NULL,
[ifi_enabled] [TINYINT] NOT NULL,
[installed_date] [DATETIME] NOT NULL,
[sql_service_account] [VARCHAR](64) NOT NULL,
[sql_agent_service_account] [VARCHAR](64) NOT NULL,
[startup_time] [DATETIME] NOT NULL,
[data_collection_timestamp] [DATETIME] NOT NULL
) ON [PRIMARY]
END
END
CREATE TABLE #CPUValues(
[index] SMALLINT,
[description] VARCHAR(128),
[server_cores] SMALLINT,
[value] VARCHAR(5)
)
CREATE TABLE #MemoryValues(
[index] SMALLINT,
[description] VARCHAR(128),
[server_memory] DECIMAL(10,2),
[value] VARCHAR(64)
)
INSERT INTO #CPUValues
EXEC xp_msver 'ProcessorCount'
INSERT INTO #MemoryValues
EXEC xp_msver 'PhysicalMemory'
CREATE TABLE #IFI_Value(DataOut VarChar(2000))
DECLARE @show_advanced_options INT
DECLARE @xp_cmdshell_enabled INT
DECLARE @xp_regread_enabled INT
SELECT @show_advanced_options = CONVERT(INT, ISNULL(value, value_in_use))
FROM master.sys.configurations
WHERE name = 'show advanced options'
IF @show_advanced_options = 0
BEGIN
EXEC sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
END
SELECT @xp_cmdshell_enabled = CONVERT(INT, ISNULL(value, value_in_use))
FROM master.sys.configurations
WHERE name = 'xp_cmdshell'
IF @xp_cmdshell_enabled = 0
BEGIN
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE WITH OVERRIDE
END
INSERT INTO #IFI_Value
EXEC xp_cmdshell 'whoami /priv | findstr `"SeManageVolumePrivilege`"'
IF @xp_cmdshell_enabled = 0
BEGIN
EXEC sp_configure 'xp_cmdshell', 0
RECONFIGURE WITH OVERRIDE
END
IF @show_advanced_options = 0
BEGIN
EXEC sp_configure 'show advanced options', 0
RECONFIGURE WITH OVERRIDE
END
IF (SELECT CONVERT(INT, (REPLACE(SUBSTRING(CONVERT(NVARCHAR, SERVERPROPERTY('ProductVersion')), 1, 2), '.', '')))) > 10
BEGIN
IF(@storeValuesInTable = 'Y')
BEGIN
SET @sqlCommand = '
INSERT INTO InstanceValues
'
END
SET @sqlCommand += '
SELECT
v.sql_version,
(SELECT SUBSTRING(CONVERT(VARCHAR(255),SERVERPROPERTY(''EDITION'')),0,CHARINDEX(''Edition'',CONVERT(VARCHAR(255),SERVERPROPERTY(''EDITION'')))) + ''Edition'') AS sql_edition,
CONVERT(VARCHAR,SERVERPROPERTY(''ProductVersion'')) AS build_number,
(SELECT CONVERT(DECIMAL(10,2),[value]) FROM sys.configurations WHERE name LIKE ''%min server memory%'') min_server_memory,
(SELECT CONVERT(DECIMAL(10,2),[value]) FROM sys.configurations WHERE name LIKE ''%max server memory%'') max_server_memory,
(SELECT ROUND(CONVERT(DECIMAL(10,2),server_memory/1024.0),1) FROM #MemoryValues) AS server_memory,
server_cores,
(SELECT COUNT(*) AS ''sql_cores'' FROM sys.dm_os_schedulers WHERE status = ''VISIBLE ONLINE'') AS sql_cores,
(SELECT CONVERT(SMALLINT,[value]) FROM sys.configurations WHERE name LIKE ''%cost threshold for parallelism%'') AS cost_threshold_for_parallelism,
(SELECT CONVERT(SMALLINT,[value]) FROM sys.configurations WHERE name LIKE ''%max degree of parallelism%'') AS max_degree_of_parallelism,
(SELECT CASE locked_page_allocations_kb WHEN 0 THEN 0 ELSE 1 END FROM sys.dm_os_process_memory) AS lpim_enabled,
(SELECT COUNT(1) FROM #IFI_Value WHERE DataOut LIKE ''%SeManageVolumePrivilege%Enabled%'') AS ifi_enabled,
(SELECT create_date FROM sys.server_principals WHERE sid = 0x010100000000000512000000) AS installed_date,
(SELECT service_account FROM sys.dm_server_services WHERE servicename = {fn CONCAT({fn CONCAT(''SQL Server ('',CONVERT(VARCHAR(32),ISNULL(SERVERPROPERTY(''INSTANCENAME''),''MSSQLSERVER'')))},'')'')}) AS sql_service_account,
(SELECT service_account FROM sys.dm_server_services WHERE servicename = {fn CONCAT({fn CONCAT(''SQL Server Agent ('',CONVERT(VARCHAR(32),ISNULL(SERVERPROPERTY(''INSTANCENAME''),''MSSQLSERVER'')))},'')'')}) AS sql_agent_service_account,
(SELECT login_time FROM sys.sysprocesses WHERE spid = 1) AS startup_time'
IF(@storeValuesInTable = 'Y')
BEGIN
SET @sqlCommand += '
,GETDATE() AS data_collection_timestamp
'
END
SET @sqlCommand += '
FROM #CPUValues
LEFT JOIN (
SELECT
CASE
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''8%'' THEN ''SQL Server 2000''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''9%'' THEN ''SQL Server 2005''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''10.0%'' THEN ''SQL Server 2008''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''10.5%'' THEN ''SQL Server 2008 R2''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''11%'' THEN ''SQL Server 2012''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''12%'' THEN ''SQL Server 2014''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''13%'' THEN ''SQL Server 2016''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''14%'' THEN ''SQL Server 2017''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''15%'' THEN ''SQL Server 2019''
ELSE ''UNKNOWN''
END AS sql_version
) AS v ON 1 = 1
'
EXECUTE(@sqlCommand)
END
ELSE
BEGIN
DECLARE @instanceName VARCHAR(100)
SET @instanceName = CONVERT(VARCHAR,SERVERPROPERTY ('InstanceName'))
IF (@instanceName) IS NULL
BEGIN
DECLARE @agentAccount NVARCHAR(128);
EXEC master.dbo.xp_regread
'HKEY_LOCAL_MACHINE',
'SYSTEM\CurrentControlSet\services\SQLSERVERAGENT',
'ObjectName',
@agentAccount OUTPUT;
DECLARE @engineAccount NVARCHAR(128);
EXEC master.dbo.xp_regread
'HKEY_LOCAL_MACHINE',
'SYSTEM\CurrentControlSet\services\MSSQLSERVER',
'ObjectName',
@engineAccount OUTPUT;
END
ELSE
BEGIN
DECLARE @SQL NVARCHAR (500)
SET @SQL = 'EXEC master.dbo.xp_regread ''HKEY_LOCAL_MACHINE'', ''SYSTEM\CurrentControlSet\services\SQLAgent$'[email protected]+''',''ObjectName'', @serviceAccount OUTPUT;'
EXECUTE sp_executesql @SQL,N'@serviceAccount NVARCHAR(128) OUTPUT',@[email protected] OUTPUT
SET @SQL = 'EXEC master.dbo.xp_regread ''HKEY_LOCAL_MACHINE'', ''SYSTEM\CurrentControlSet\services\MSSQL$'[email protected]+''',''ObjectName'', @serviceAccount OUTPUT;'
EXECUTE sp_executesql @SQL,N'@serviceAccount NVARCHAR(128) OUTPUT',@[email protected] OUTPUT
END
IF(@storeValuesInTable = 'Y')
BEGIN
SET @sqlCommand = '
INSERT INTO InstanceValues
'
END
SET @sqlCommand += '
SELECT
v.sql_version,
(SELECT SUBSTRING(CONVERT(VARCHAR(255),SERVERPROPERTY(''EDITION'')),0,CHARINDEX(''Edition'',CONVERT(VARCHAR(255),SERVERPROPERTY(''EDITION'')))) + ''Edition'') AS sql_edition,
CONVERT(VARCHAR,SERVERPROPERTY(''ProductVersion'')) AS build_number,
(SELECT CONVERT(DECIMAL(10,2),[value]) FROM sys.configurations WHERE name LIKE ''%min server memory%'') min_server_memory,
(SELECT CONVERT(DECIMAL(10,2),[value]) FROM sys.configurations WHERE name LIKE ''%max server memory%'') max_server_memory,
(SELECT ROUND(CONVERT(DECIMAL(10,2),server_memory/1024.0),1) FROM #MemoryValues) AS server_memory,
server_cores,
(SELECT COUNT(*) AS sql_cores FROM sys.dm_os_schedulers WHERE status = ''VISIBLE ONLINE'') AS sql_cores,
(SELECT CONVERT(SMALLINT,[value]) FROM sys.configurations WHERE name LIKE ''%cost threshold for parallelism%'') AS cost_threshold_for_parallelism,
(SELECT CONVERT(SMALLINT,[value]) FROM sys.configurations WHERE name LIKE ''%max degree of parallelism%'') AS max_degree_of_parallelism,
(SELECT CASE locked_page_allocations_kb WHEN 0 THEN 0 ELSE 1 END FROM sys.dm_os_process_memory) AS lpim_enabled,
(SELECT COUNT(1) FROM #IFI_Value WHERE DataOut LIKE ''%SeManageVolumePrivilege%Enabled%'') AS ifi_enabled,
(SELECT create_date FROM sys.server_principals WHERE sid = 0x010100000000000512000000) AS installed_date,
(SELECT '+CHAR(39)[email protected]+CHAR(39)+' AS sql_service_account) AS sql_service_account,
(SELECT '+CHAR(39)[email protected]+CHAR(39)+' AS sql_agent_service_account) AS sql_agent_service_account,
(SELECT login_time FROM sys.sysprocesses WHERE spid = 1) AS startup_time'
IF(@storeValuesInTable = 'Y')
BEGIN
SET @sqlCommand += '
,GETDATE() AS data_collection_timestamp
'
END
SET @sqlCommand += '
FROM #CPUValues
LEFT JOIN (
SELECT
CASE
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''8%'' THEN ''SQL Server 2000''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''9%'' THEN ''SQL Server 2005''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''10.0%'' THEN ''SQL Server 2008''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''10.5%'' THEN ''SQL Server 2008 R2''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''11%'' THEN ''SQL Server 2012''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''12%'' THEN ''SQL Server 2014''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''13%'' THEN ''SQL Server 2016''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''14%'' THEN ''SQL Server 2017''
WHEN CONVERT(VARCHAR(128), SERVERPROPERTY (''PRODUCTVERSION'')) LIKE ''15%'' THEN ''SQL Server 2019''
ELSE ''UNKNOWN''
END AS sql_version
) AS v ON 1 = 1
'
EXECUTE(@sqlCommand)
--SELECT @sqlCommand
END
DROP TABLE #CPUValues
DROP TABLE #MemoryValues
DROP TABLE #IFI_Value
END
Závěr
Vlastní uložená procedura uvedená v tomto článku vám umožňuje sestavit výstražný mechanismus, který vás upozorní na změny jakýchkoli hodnot určitého pole v průběhu času.
Tento SP můžete nasadit v každé instanci SQL Serveru v rámci vaší podpory a implementovat mechanismus auditu v celém svém zásobníku podporovaných instancí.
Primární důležitost prezentovaných informací by byla kontrola, zda instance SQL Server má hodnoty, které jsou dodržovány doporučenými osvědčenými postupy. Pomůže vám také zkontrolovat, zda nedošlo k nějaké nedávné aktivitě/změně za účelem aktualizace některého z nastavení (ať už záměrně, nebo omylem).