Database
 sql >> Database >  >> RDS >> Database

Stored procedure per ottenere le impostazioni dell'istanza

Le istanze di SQL Server ospitano database contenenti i dati per lo stack back-end di un modello di business o dati di configurazione per applicazioni particolari. Indipendentemente dal caso d'uso, un'istanza ha una serie di valori/impostazioni che devono essere ottimizzati per seguire le migliori pratiche.

Lo scopo della stored procedure che sto mostrando in questo articolo è presentare al DBA un insieme di impostazioni/valori importanti che non dovrebbero essere trascurati. Inoltre, condividerò un'interessante funzionalità che aiuta i DBA a mantenere il controllo di qualsiasi impostazione/valore particolare che è stato recentemente cambiato/modificato.

Considerazioni iniziali

Assicurati che l'account che utilizzerai per eseguire questa stored procedure disponga di privilegi sufficienti. So che chiedere un utente con privilegio di amministratore di sistema sembra troppo, ma è il modo più semplice per farlo funzionare correttamente, dal momento che l'SP usa xp_cmdshell e altre procedure speciali di sistema memorizzate per portare a termine il lavoro. In alternativa, puoi regolare i diritti dell'utente in modo che aderiscano al principio del privilegio minimo.

Come utilizzare la stored procedure SQL?

  1. Copia e incolla il codice SP TSQL fornito in questo articolo.
  2. L'SP prevede un solo parametro:@  storeValuesInTable

è se il DBA desidera salvare l'output in una tabella di destinazione e N è se il DBA vuole solo vedere l'output direttamente.

Campi presentati e loro significato

  • versione_sql la versione corrente di SQL Server dell'istanza.
  • edizione_sql l'edizione corrente di SQL Server dell'istanza.
  • build_number il numero di build corrente dell'istanza.
  • Memoria_server_minima il valore corrente (in MB) assegnato alla Memoria Min Server.
  • memoria_server_max il valore corrente (in MB) assegnato alla Max Server Memory.
  • memoria_server il valore corrente (in MB) disponibile sul server che ospita l'istanza di SQL Server.
  • core_server la quantità di core vCPU di cui dispone il server che ospita l'istanza di SQL Server.
  • sql_cores la quantità di core vCPU che l'istanza di SQL Server ha assegnato per il suo utilizzo.
  • soglia_di_costo_per_parallelismo il valore corrente assegnato per l'impostazione Soglia di costo per il parallelismo.
  • max_grado_di_parallelismo il valore corrente assegnato per l'impostazione del grado massimo di parallelismo.
  • lpim_enabled 0 se Blocca pagine in memoria l'impostazione è disabilitata e 1 se abilitata.
  • ifi_enabled 0 se Inizializzazione file istantanea è disabilitato e 1 se abilitato.
  • data_installazione la data e l'ora di installazione dell'istanza di SQL Server.
  • sql_service_account l'account di servizio che eseguirà il servizio DB Engine.
  • sql_agent_service_account l'account di servizio che eseguirà il servizio Agent.
  • ora_avvio valore di data e ora quando l'istanza di SQL Server è stata avviata di recente.
  • data_collection_timestamp visibile solo se S è passato alla SP. Viene utilizzato per definire quando l'SP è stato eseguito e salvato con successo le informazioni in InstanceValues tabella.

Test di esecuzione della stored procedure in SQL

Dimostrerò alcune esecuzioni della Stored Procedure in modo da farti un'idea di cosa aspettarti.

EXEC DBA_InstanceValues @storeValuesInTable = 'N'
EXEC DBA_InstanceValues @storeValuesInTable = 'Y'

Per questa particolare esecuzione, l'output verrà salvato in una tabella denominata InstanceValues . Verrà creato nel database di destinazione se non esiste.

La tabella ha quasi la stessa struttura dello screenshot sopra, con una piccola differenza:include un campo chiamato data_collection_timestamp proprio alla fine della tavola.

Il data_collection_timestamp campo è utile per diversi scopi:

  • per dirti quando è stato eseguito l'SP per raccogliere i dati salvati (abbastanza ovvio).
  • Cercare eventuali differenze entro un determinato intervallo di tempo per un campo di impostazione particolare.

Per dimostrare che è utile, vorrei presentare un rapido esempio.

Ho eseguito la SP una volta, passando la Y parametro. Il rispettivo record è stato inserito negli InstanceValues tavolo. Quindi cambio costo_soglia_per_parallelismo valore all'interno della mia istanza a 50 , quindi esegui di nuovo lo script.

Come puoi vedere, la modifica è stata registrata correttamente in InstanceValues tavolo. Ora, come può essere utile?

Se crei un lavoro agente che esegue questa procedura archiviata su base giornaliera, puoi creare un meccanismo di controllo interno per tenere traccia di quando un particolare valore di impostazione viene modificato, proprio come ho dimostrato. Pertanto, puoi mantenere il controllo completo sulla tua istanza di SQL Server. Se me lo chiedi, è qualcosa di estremamente utile.

Il Codice Completo della Stored Procedure

All'inizio dello script, vedrai il valore predefinito. La stored procedure lo presuppone se nessun valore viene passato al parametro.

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

Conclusione

La stored procedure personalizzata presentata in questo articolo consente di creare un meccanismo di avviso per notificare le modifiche di qualsiasi valore di un determinato campo nel tempo.

Puoi distribuire questo SP in ogni istanza di SQL Server supportata e implementare il meccanismo di controllo nell'intero stack di istanze supportate.

L'importanza principale delle informazioni presentate sarebbe verificare se l'istanza di SQL Server ha valori che rispettano le procedure consigliate. Ti aiuta anche a verificare se sono state apportate attività/modifiche recenti per aggiornare le impostazioni (intenzionalmente o per errore).