sql >> Database >  >> RDS >> Database

De opgeslagen procedure om de instantie-instellingen op te halen

SQL Server-instanties bevatten databases met de gegevens voor de backend-stack van een bedrijfsmodel of configuratiegegevens voor bepaalde toepassingen. Ongeacht de gebruikssituatie heeft een instantie een reeks waarden/instellingen die moeten worden afgestemd om de best practices te volgen.

Het doel van de opgeslagen procedure die ik in dit artikel laat zien, is om de DBA een reeks belangrijke instellingen/waarden te presenteren die niet over het hoofd mogen worden gezien. Bovendien zal ik een coole functie delen waarmee DBA's controle kunnen houden over een bepaalde instelling/waarde die onlangs is gewijzigd/aangepast.

Eerste overwegingen

Zorg ervoor dat het account dat u gaat gebruiken om deze Opgeslagen Procedure uit te voeren voldoende privileges heeft. Ik weet dat vragen om een ​​gebruiker met sysadmin-rechten veel te veel klinkt, maar het is de gemakkelijkste manier om het goed te laten werken, aangezien de SP xp_cmdshell gebruikt en andere speciale door het systeem opgeslagen procedures om de klus te klaren. Of u kunt de gebruikersrechten afstemmen op het principe van de minste bevoegdheden.

Hoe de opgeslagen SQL-procedure gebruiken?

  1. Kopieer en plak de SP TSQL-code in dit artikel.
  2. De SP verwacht slechts 1 parameter:@  storeValuesInTable

J is als de DBA de uitvoer in een doeltabel wil opslaan, en N is als de DBA de uitvoer alleen rechtstreeks wil zien.

Gepresenteerde velden en hun betekenis

  • sql_version de huidige SQL Server-versie van de instantie.
  • sql_edition de huidige SQL Server-editie van de instantie.
  • build_number het huidige buildnummer van de instantie.
  • min_server_memory de huidige waarde (in MB) die is toegewezen aan het Min Server Memory.
  • max_server_memory de huidige waarde (in MB) die is toegewezen aan het Max Server Memory.
  • server_memory de huidige waarde (in MB) die de server die de SQL Server-instantie host, beschikbaar heeft.
  • server_cores het aantal vCPU-cores dat de server die de SQL Server-instantie host, heeft.
  • sql_cores het aantal vCPU-cores dat de SQL Server-instantie heeft toegewezen voor het gebruik ervan.
  • cost_threshold_for_parallelism de huidige waarde die is toegewezen voor de instelling Kostendrempel voor parallellisme.
  • max_degree_of_parallelism de huidige waarde die is toegewezen voor de instelling Max. graad van parallellisme.
  • lpim_enabled 0 als Pagina's in het geheugen vergrendelen instelling is uitgeschakeld en 1 indien ingeschakeld.
  • ifi_enabled 0 als Initialisatie van direct bestand is uitgeschakeld en 1 indien ingeschakeld.
  • installed_date de datum en tijd waarop de SQL Server-instantie is geïnstalleerd.
  • sql_service_account het serviceaccount dat de DB Engine-service zal uitvoeren.
  • sql_agent_service_account het serviceaccount dat de Agent-service zal uitvoeren.
  • startup_time datum- en tijdwaarde wanneer de SQL Server-instantie onlangs is gestart.
  • data_collection_timestamp alleen zichtbaar als J wordt doorgegeven aan de SP. Het wordt gebruikt om te definiëren wanneer de SP is uitgevoerd en de informatie met succes is opgeslagen in de InstanceValues tafel.

Uitvoeringstests van de opgeslagen procedure in SQL

Ik zal een paar uitvoeringen van de Opgeslagen Procedure demonstreren, zodat u een idee krijgt wat u ervan kunt verwachten.

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

Voor deze specifieke uitvoering wordt de uitvoer opgeslagen in een tabel met de naam InstanceValues . Het wordt aangemaakt in de doeldatabase als het niet bestaat.

De tabel heeft bijna dezelfde structuur als op de schermafbeelding hierboven, met een klein verschil:het bevat een veld met de naam data_collection_timestamp helemaal aan het einde van de tafel.

De data_collection_timestamp veld is nuttig voor verschillende doeleinden:

  • om u te vertellen wanneer de SP werd uitgevoerd om de opgeslagen gegevens te verzamelen (vrij duidelijk).
  • Om binnen een bepaald tijdsbestek eventuele verschillen te zoeken voor een bepaald instellingsveld.

Om te bewijzen dat het nuttig is, zal ik een snel voorbeeld geven.

Ik heb de SP een keer uitgevoerd, waarbij ik de Y . heb gepasseerd parameter. Het respectieve record is ingevoegd in de InstanceValues tafel. Dan verander ik cost_threshold_for_parallelism waarde binnen mijn instantie tot 50 en voer het script vervolgens opnieuw uit.

Zoals u kunt zien, is de wijziging succesvol vastgelegd in de InstanceValues tafel. Hoe kan dit nu nuttig zijn?

Als u een agenttaak maakt die deze opgeslagen procedure dagelijks uitvoert, kunt u een intern auditmechanisme maken om bij te houden wanneer een bepaalde instellingswaarde wordt gewijzigd, zoals ik heb laten zien. Zo houdt u de volledige controle over uw SQL Server-instantie. Als je het mij vraagt, is het iets heel nuttigs.

De volledige code van de opgeslagen procedure

Helemaal aan het begin van het script ziet u de standaardwaarde. De Opgeslagen Procedure gaat ervan uit dat er geen waarde wordt doorgegeven aan de parameter.

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

Conclusie

Met de aangepaste opgeslagen procedure die in dit artikel wordt gepresenteerd, kunt u een waarschuwingsmechanisme bouwen om in de loop van de tijd op de hoogte te blijven van wijzigingen van waarden van een bepaald veld.

U kunt deze SP in elke SQL Server-instantie onder uw steun implementeren en het controlemechanisme implementeren voor uw hele stapel ondersteunde instanties.

Het belangrijkste belang van de gepresenteerde informatie is om te controleren of het SQL Server-exemplaar waarden heeft die voldoen aan de aanbevolen aanbevolen procedures. Het helpt je ook om te controleren of er recente activiteit/wijziging heeft plaatsgevonden om de instellingen bij te werken (opzettelijk of per ongeluk).


  1. Hoe u alle mogelijke combinaties van rijen uit twee tabellen in SQL kunt krijgen

  2. NULL-type casten bij het bijwerken van meerdere rijen

  3. Postgres wijzigt handmatig de volgorde

  4. Proactieve PostgreSQL-monitoring (hoek voor ontwikkelaarsstudio/adviseurs)