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

Die gespeicherte Prozedur zum Abrufen der Instanzeinstellungen

SQL Server-Instanzen enthalten Datenbanken, die die Daten für den Backend-Stack eines Geschäftsmodells oder Konfigurationsdaten für bestimmte Anwendungen enthalten. Unabhängig vom Anwendungsfall hat eine Instanz eine Reihe von Werten/Einstellungen, die angepasst werden sollten, um Best Practices zu folgen.

Der Zweck der gespeicherten Prozedur, die ich in diesem Artikel vorstelle, besteht darin, dem DBA eine Reihe wichtiger Einstellungen/Werte zu präsentieren, die nicht übersehen werden sollten. Darüber hinaus werde ich eine coole Funktion vorstellen, die DBAs hilft, die Kontrolle über bestimmte Einstellungen/Werte zu behalten, die kürzlich geändert/modifiziert wurden.

Erste Überlegungen

Stellen Sie sicher, dass das Konto, das Sie zum Ausführen dieser gespeicherten Prozedur verwenden, über ausreichende Berechtigungen verfügt. Ich weiß, dass die Frage nach einem Benutzer mit Sysadmin-Privilegien viel zu viel klingt, aber es ist der einfachste Weg, es richtig zum Laufen zu bringen, da der SP xp_cmdshell verwendet und andere spezielle gespeicherte Systemprozeduren, um die Arbeit zu erledigen. Oder Sie können die Rechte des Benutzers anpassen, um das Prinzip der geringsten Rechte einzuhalten.

Wie verwende ich die gespeicherte SQL-Prozedur?

  1. Kopieren Sie den in diesem Artikel bereitgestellten SP-TSQL-Code und fügen Sie ihn ein.
  2. Der SP erwartet nur 1 Parameter:@  storeValuesInTable

Ja ist, wenn der DBA die Ausgabe in einer Zieltabelle speichern möchte, und N ist, wenn der DBA die Ausgabe nur direkt sehen möchte.

Dargestellte Felder und ihre Bedeutung

  • sql_version die aktuelle SQL Server-Version der Instanz.
  • sql_edition die aktuelle SQL Server-Edition der Instanz.
  • Buildnummer die aktuelle Build-Nummer der Instanz.
  • min_server_memory der aktuelle Wert (in MB), der dem minimalen Serverspeicher zugewiesen ist.
  • max_server_memory der aktuelle Wert (in MB), der dem maximalen Serverspeicher zugewiesen ist.
  • Serverspeicher der aktuelle Wert (in MB), den der Server, der die SQL Server-Instanz hostet, zur Verfügung hat.
  • server_cores die Anzahl der vCPU-Kerne, über die der Server verfügt, der die SQL Server-Instanz hostet.
  • sql_cores die Menge an vCPU-Kernen, die die SQL Server-Instanz für ihre Nutzung zugewiesen hat.
  • cost_threshold_for_parallelism der aktuelle Wert, der der Einstellung „Kostenschwellenwert für Parallelität“ zugewiesen ist.
  • max_parallelitätsgrad_ der aktuelle Wert, der der Einstellung „Max. Grad an Parallelität“ zugewiesen ist.
  • lpim_enabled 0, wenn Seiten im Speicher sperren Die Einstellung ist deaktiviert und 1, wenn sie aktiviert ist.
  • ifi_enabled 0 bei Sofortige Dateiinitialisierung ist deaktiviert und 1, wenn aktiviert.
  • Installationsdatum Datum und Uhrzeit der Installation der SQL Server-Instanz.
  • sql_service_account das Dienstkonto, das den DB Engine-Dienst ausführt.
  • sql_agent_service_account das Dienstkonto, das den Agent-Dienst ausführt.
  • Startzeit Datums- und Uhrzeitwert, wann die SQL Server-Instanz kürzlich gestartet wurde.
  • data_collection_timestamp nur sichtbar, wenn Y wird an den SP weitergegeben. Es wird verwendet, um zu definieren, wann der SP ausgeführt und die Informationen erfolgreich in den InstanceValues gespeichert wurden Tabelle.

Ausführungstests der gespeicherten Prozedur in SQL

Ich werde einige Ausführungen der gespeicherten Prozedur demonstrieren, damit Sie eine Vorstellung davon bekommen, was Sie davon erwarten können.

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

Für diese spezielle Ausführung wird die Ausgabe in einer Tabelle namens InstanceValues gespeichert . Es wird in der Zieldatenbank erstellt, wenn es nicht existiert.

Die Tabelle hat fast dieselbe Struktur wie im obigen Screenshot, mit einem kleinen Unterschied:Sie enthält ein Feld namens data_collection_timestamp ganz am Ende der Tabelle.

Der data_collection_timestamp Feld ist für mehrere Zwecke hilfreich:

  • um Ihnen mitzuteilen, wann der SP ausgeführt wurde, um die gespeicherten Daten zu sammeln (ziemlich offensichtlich).
  • Zur Suche nach Unterschieden innerhalb eines bestimmten Zeitraums für ein bestimmtes Einstellungsfeld.

Lassen Sie mich ein kurzes Beispiel präsentieren, um zu beweisen, dass es nützlich ist.

Ich habe den SP einmal ausgeführt und das Y bestanden Parameter. Der entsprechende Datensatz wurde in die InstanceValues eingefügt Tisch. Dann ändere ich cost_threshold_for_parallelism -Wert in meiner Instanz auf 50 , und führen Sie das Skript erneut aus.

Wie Sie sehen können, wurde die Änderung erfolgreich in den InstanceValues protokolliert Tisch. Nun, wie kann das nützlich sein?

Wenn Sie einen Agentenjob erstellen, der diese gespeicherte Prozedur täglich ausführt, können Sie einen internen Prüfmechanismus erstellen um zu verfolgen, wann ein bestimmter Einstellungswert geändert wird, genau wie ich es demonstriert habe. Somit behalten Sie die volle Kontrolle über Ihre SQL Server Instanz. Wenn Sie mich fragen, ist es etwas äußerst Nützliches.

Der vollständige Code der gespeicherten Prozedur

Ganz am Anfang des Skripts sehen Sie den Standardwert. Die gespeicherte Prozedur geht davon aus, wenn dem Parameter kein Wert übergeben wird.

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

Schlussfolgerung

Die in diesem Artikel vorgestellte benutzerdefinierte gespeicherte Prozedur ermöglicht es Ihnen, einen Warnmechanismus zu erstellen, um über Änderungen von Werten eines bestimmten Felds im Laufe der Zeit zu informieren.

Sie können diesen SP in jeder von Ihnen unterstützten SQL Server-Instanz bereitstellen und den Prüfmechanismus für Ihren gesamten Stack unterstützter Instanzen implementieren.

Die wichtigste Bedeutung der präsentierten Informationen besteht darin, zu überprüfen, ob die SQL Server-Instanz über Werte verfügt, die den empfohlenen Best Practices entsprechen. Es hilft Ihnen auch zu überprüfen, ob kürzlich Aktivitäten/Änderungen vorgenommen wurden, um Einstellungen zu aktualisieren (entweder absichtlich oder versehentlich).