Database
 sql >> Base de données >  >> RDS >> Database

La procédure stockée pour obtenir les paramètres d'instance

Les instances SQL Server hébergent des bases de données contenant les données de la pile principale d'un modèle commercial ou des données de configuration pour des applications particulières. Quel que soit le cas d'utilisation, une instance possède un ensemble de valeurs/paramètres qui doivent être réglés pour suivre les meilleures pratiques.

Le but de la procédure stockée que je présente dans cet article est de présenter au DBA un ensemble de paramètres/valeurs importants à ne pas négliger. De plus, je partagerai une fonctionnalité intéressante qui aide les DBA à garder le contrôle de tout paramètre/valeur particulier qui a été récemment changé/modifié.

Considérations initiales

Assurez-vous que le compte que vous utiliserez pour exécuter cette procédure stockée dispose de suffisamment de privilèges. Je sais que demander un utilisateur avec le privilège sysadmin semble beaucoup trop, mais c'est le moyen le plus simple de le faire fonctionner correctement, car le SP utilise xp_cmdshell et d'autres procédures système spéciales stockées pour faire le travail. Ou, vous pouvez ajuster les droits de l'utilisateur pour adhérer au principe du moindre privilège.

Comment utiliser la procédure stockée SQL ?

  1. Copiez et collez le code SP TSQL fourni dans cet article.
  2. Le SP attend 1 paramètre uniquement :@  storeValuesInTable

Oui est si le DBA souhaite enregistrer la sortie dans une table cible, et N est si le DBA ne veut voir que la sortie directement.

Champs présentés et leurs significations

  • version_sql la version actuelle de SQL Server de l'instance.
  • sql_edition l'édition SQL Server actuelle de l'instance.
  • build_number le numéro de build actuel de l'instance.
  • min_server_memory la valeur actuelle (en Mo) attribuée à la mémoire minimale du serveur.
  • max_server_memory la valeur actuelle (en Mo) attribuée à la mémoire maximale du serveur.
  • server_memory la valeur actuelle (en Mo) dont dispose le serveur hébergeant l'instance SQL Server.
  • server_cores la quantité de cœurs vCPU dont dispose le serveur hébergeant l'instance SQL Server.
  • sql_cores la quantité de cœurs vCPU que l'instance SQL Server a attribuée pour son utilisation.
  • cost_threshold_for_parallelism la valeur actuelle attribuée au paramètre Seuil de coût pour le parallélisme.
  • max_degree_of_parallelism la valeur actuelle attribuée au paramètre Degré maximal de parallélisme.
  • lpim_enabled 0 si Verrouiller les pages en mémoire paramètre est désactivé et 1 s'il est activé.
  • ifi_enabled 0 si initialisation instantanée du fichier est désactivé et 1 si activé.
  • installed_date la date et l'heure d'installation de l'instance SQL Server.
  • sql_service_account le compte de service qui exécutera le service DB Engine.
  • sql_agent_service_account le compte de service qui exécutera le service Agent.
  • startup_time valeur de date et d'heure lorsque l'instance SQL Server a récemment démarré.
  • data_collection_timestamp visible uniquement si Y est transmis au SP. Il est utilisé pour définir quand le SP a été exécuté et a enregistré avec succès les informations dans les InstanceValues tableau.

Tests d'exécution de la procédure stockée en SQL

Je vais vous montrer quelques exécutions de la procédure stockée afin que vous ayez une idée de ce que vous pouvez en attendre.

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

Pour cette exécution particulière, la sortie sera enregistrée dans une table appelée InstanceValues . Il sera créé dans la base de données cible s'il n'existe pas.

La table a presque la même structure que sur la capture d'écran ci-dessus, avec une petite différence :elle inclut un champ appelé data_collection_timestamp tout au bout du tableau.

Le data_collection_timestamp champ est utile à plusieurs fins :

  • pour vous dire quand le SP a été exécuté pour collecter les données sauvegardées (assez évident).
  • Pour rechercher les différences dans une plage de temps particulière pour un champ de paramètre particulier.

Pour prouver que c'est utile, permettez-moi de vous présenter un exemple rapide.

J'ai exécuté le SP une fois, en passant le Y paramètre. L'enregistrement respectif a été inséré dans les InstanceValues table. Ensuite, je change cost_threshold_for_parallelism valeur dans mon instance à 50 , puis exécutez à nouveau le script.

Comme vous pouvez le voir, la modification a été enregistrée avec succès dans les InstanceValues table. Maintenant, comment cela peut-il être utile ?

Si vous créez un travail d'agent qui exécute quotidiennement cette procédure stockée, vous pouvez créer un mécanisme d'audit interne pour garder une trace du moment où une valeur de réglage particulière est modifiée, comme je l'ai démontré. Ainsi, vous pouvez garder un contrôle total sur votre instance SQL Server. Si vous me demandez, c'est quelque chose d'extrêmement utile.

Le code complet de la procédure stockée

Au tout début du script, vous verrez la valeur par défaut. La procédure stockée l'assume si aucune valeur n'est transmise au paramètre.

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

Conclusion

La procédure stockée personnalisée présentée dans cet article vous permet de créer un mécanisme d'alerte pour notifier les modifications de toutes les valeurs d'un champ particulier au fil du temps.

Vous pouvez déployer ce SP dans chaque instance SQL Server sous votre support et mettre en œuvre le mécanisme d'audit sur l'ensemble de votre pile d'instances prises en charge.

L'importance primordiale des informations présentées serait de vérifier si l'instance SQL Server a des valeurs qui sont conformes aux meilleures pratiques recommandées. Il vous aide également à vérifier si une activité/modification récente a eu lieu pour mettre à jour l'un des paramètres (soit intentionnellement, soit par erreur).