Diskusi kami tentang tugas proaktif yang menjaga database Anda tetap sehat berlanjut di posting ini saat kami menangani opsi server dan database. Anda mungkin sudah berpikir ini akan menjadi posting cepat – siapa yang sering mengubah opsi server atau database? Anda akan terkejut, terutama jika Anda memiliki banyak orang yang memiliki akses ke SQL Server. Opsi server dan basis data harus jarang berubah – sebagian besar disetel saat penginstalan dan dibiarkan sendiri. Tetapi seringkali ada alasan bagus untuk melakukan perubahan – baik itu terkait kinerja, karena perubahan kode aplikasi, atau mungkin karena ada sesuatu yang salah disetel pertama kali. Uji perubahan ini terlebih dahulu, dan tangkap metrik yang sesuai sebelum dan sesudah perubahan. Tampaknya cukup mudah dan jelas, bukan? Anda mungkin berpikir begitu, tetapi jika Anda tidak memiliki proses manajemen perubahan yang diikuti secara ketat, itu tidak akan terjadi.
Di sebagian besar lingkungan, lebih dari satu orang memiliki akses ke SQL Server, dan lebih dari satu orang memiliki hak istimewa yang diperlukan untuk mengubah opsi server atau database. Jika pengaturan yang salah diubah, dampak kinerja dapat menjadi signifikan. (Pernahkah Anda secara tidak sengaja mengatur pengaturan memori maksimum ke nilai dalam GB, bukan MB? Jika Anda bertanya-tanya, 128MB tidak cukup memori yang diperlukan untuk memulai instance SQL Server. Lihat posting Ted Krueger tentang cara memperbaikinya , jika Anda pernah melakukan kesalahan itu.) Perubahan lain dapat membuat masalah kecil yang masih menyusahkan dan terkadang sulit dilacak (menonaktifkan Auto Create Statistics adalah contoh yang baik). Anda mungkin berpikir bahwa perubahan ini akan dikomunikasikan dengan baik (terkadang Anda begitu sibuk memadamkan api sehingga Anda lupa) atau mudah diperhatikan (tidak selalu). Untuk menghindari hal ini, kami melacak setelan dan kemudian, saat menjalankan pemeriksaan rutin kami (atau saat memecahkan masalah), kami memverifikasi bahwa tidak ada yang berubah.
Mengambil Data
Tidak seperti posting sebelumnya tentang tugas pemeliharaan, di mana kami mengandalkan msdb untuk menyimpan data yang kami pedulikan, kami harus mengatur pengambilan data misalnya dan pengaturan basis data. Kami akan mengambil snapshot sys.configurations dan sys.database_info setiap hari ke tabel di database Baselines kami, lalu menggunakan kueri untuk melihat apakah ada yang berubah, dan kapan.
USE [Baselines]; GO IF OBJECT_ID(N'dbo.SQLskills_ConfigData', N'U') IS NULL BEGIN CREATE TABLE [dbo].[SQLskills_ConfigData] ( [ConfigurationID] [int] NOT NULL , [Name] [nvarchar](35) NOT NULL , [Value] [sql_variant] NULL , [ValueInUse] [sql_variant] NULL , [CaptureDate] [datetime] NOT NULL DEFAULT SYSDATETIME() ) ON [PRIMARY]; GO CREATE CLUSTERED INDEX [CI_SQLskills_ConfigData] ON [dbo].[SQLskills_ConfigData] ([CaptureDate],[ConfigurationID]); GO IF OBJECT_ID(N'dbo.SQLskills_DBData', N'U') IS NULL BEGIN CREATE TABLE [dbo].[SQLskills_DBData] ( [name] [sysname] NOT NULL, [database_id] [int] NOT NULL, [source_database_id] [int] NULL, [owner_sid] [varbinary](85) NULL, [create_date] [datetime] NOT NULL, [compatibility_level] [tinyint] NOT NULL, [collation_name] [sysname] NULL, [user_access] [tinyint] NULL, [user_access_desc] [nvarchar](60) NULL, [is_read_only] [bit] NULL, [is_auto_close_on] [bit] NOT NULL, [is_auto_shrink_on] [bit] NULL, [state] [tinyint] NULL, [state_desc] [nvarchar](60) NULL, [is_in_standby] [bit] NULL, [is_cleanly_shutdown] [bit] NULL, [is_supplemental_logging_enabled] [bit] NULL, [snapshot_isolation_state] [tinyint] NULL, [snapshot_isolation_state_desc] [nvarchar](60) NULL, [is_read_committed_snapshot_on] [bit] NULL, [recovery_model] [tinyint] NULL, [recovery_model_desc] [nvarchar](60) NULL, [page_verify_option] [tinyint] NULL, [page_verify_option_desc] [nvarchar](60) NULL, [is_auto_create_stats_on] [bit] NULL, [is_auto_update_stats_on] [bit] NULL, [is_auto_update_stats_async_on] [bit] NULL, [is_ansi_null_default_on] [bit] NULL, [is_ansi_nulls_on] [bit] NULL, [is_ansi_padding_on] [bit] NULL, [is_ansi_warnings_on] [bit] NULL, [is_arithabort_on] [bit] NULL, [is_concat_null_yields_null_on] [bit] NULL, [is_numeric_roundabort_on] [bit] NULL, [is_quoted_identifier_on] [bit] NULL, [is_recursive_triggers_on] [bit] NULL, [is_cursor_close_on_commit_on] [bit] NULL, [is_local_cursor_default] [bit] NULL, [is_fulltext_enabled] [bit] NULL, [is_trustworthy_on] [bit] NULL, [is_db_chaining_on] [bit] NULL, [is_parameterization_forced] [bit] NULL, [is_master_key_encrypted_by_server] [bit] NOT NULL, [is_published] [bit] NOT NULL, [is_subscribed] [bit] NOT NULL, [is_merge_published] [bit] NOT NULL, [is_distributor] [bit] NOT NULL, [is_sync_with_backup] [bit] NOT NULL, [service_broker_guid] [uniqueidentifier] NOT NULL, [is_broker_enabled] [bit] NOT NULL, [log_reuse_wait] [tinyint] NULL, [log_reuse_wait_desc] [nvarchar](60) NULL, [is_date_correlation_on] [bit] NOT NULL, [is_cdc_enabled] [bit] NOT NULL, [is_encrypted] [bit] NULL, [is_honor_broker_priority_on] [bit] NULL, [replica_id] [uniqueidentifier] NULL, [group_database_id] [uniqueidentifier] NULL, [default_language_lcid] [smallint] NULL, [default_language_name] [nvarchar](128) NULL, [default_fulltext_language_lcid] [int] NULL, [default_fulltext_language_name] [nvarchar](128) NULL, [is_nested_triggers_on] [bit] NULL, [is_transform_noise_words_on] [bit] NULL, [two_digit_year_cutoff] [smallint] NULL, [containment] [tinyint] NULL, [containment_desc] [nvarchar](60) NULL, [target_recovery_time_in_seconds] [int] NULL, [CaptureDate] [datetime] NOT NULL DEFAULT SYSDATETIME() ) ON [PRIMARY]; GO CREATE CLUSTERED INDEX [CI_SQLskills_DBData] ON [dbo].[SQLskills_DBData] ([CaptureDate],[database_id]); GO
Skrip untuk membuat tabel SQLskills_DBData kompatibel dengan SQL Server 2014. Untuk versi sebelumnya, Anda mungkin perlu mengubah tabel dasar dan kueri snapshot (lihat rangkaian kode berikutnya).
Setelah tabel dibuat, buat pekerjaan yang akan menjalankan dua kueri berikut setiap hari. Sekali lagi, kami tidak berharap bahwa opsi ini akan berubah lebih dari sekali sehari, dan sementara kami berharap tidak ada yang akan mengubah pengaturan, lalu mengubahnya kembali (karena itu tidak akan muncul dalam pengambilan), itu selalu kemungkinan . Jika Anda menemukan bahwa pengambilan data ini tidak sesuai dengan kebutuhan Anda, karena setelan sering berubah atau sementara, Anda mungkin ingin menerapkan pemicu atau menggunakan audit.
Untuk mengedit opsi server melalui (sp_configure), login memerlukan izin tingkat server ALTER SETTINGS, yang disertakan jika Anda adalah anggota peran sysadmin atau serveradmin. Untuk mengedit sebagian besar pengaturan database (ALTER DATABASE SET), Anda memerlukan izin ALTER dalam database, meskipun beberapa opsi memerlukan hak tambahan, seperti CONTROL SERVER atau opsi tingkat server ALTER ANY DATABASE.
/* Statements to use in scheduled job */ INSERT INTO [dbo].[SQLskills_ConfigData] ( [ConfigurationID] , [Name] , [Value] , [ValueInUse] ) SELECT [configuration_id] , [name] , [value] , [value_in_use] FROM [sys].[configurations]; GO INSERT INTO [dbo].[SQLskills_DBData] ( [name], [database_id], [source_database_id], [owner_sid], [create_date], [compatibility_level], [collation_name], [user_access], [user_access_desc], [is_read_only], [is_auto_close_on], [is_auto_shrink_on], [state], [state_desc], [is_in_standby], [is_cleanly_shutdown], [is_supplemental_logging_enabled], [snapshot_isolation_state], [snapshot_isolation_state_desc], [is_read_committed_snapshot_on], [recovery_model], [recovery_model_desc], [page_verify_option], [page_verify_option_desc], [is_auto_create_stats_on], [is_auto_update_stats_on], [is_auto_update_stats_async_on], [is_ansi_null_default_on], [is_ansi_nulls_on], [is_ansi_padding_on], [is_ansi_warnings_on], [is_arithabort_on], [is_concat_null_yields_null_on], [is_numeric_roundabort_on], [is_quoted_identifier_on], [is_recursive_triggers_on], [is_cursor_close_on_commit_on], [is_local_cursor_default], [is_fulltext_enabled], [is_trustworthy_on], [is_db_chaining_on], [is_parameterization_forced], [is_master_key_encrypted_by_server], [is_published], [is_subscribed], [is_merge_published], [is_distributor], [is_sync_with_backup], [service_broker_guid], [is_broker_enabled], [log_reuse_wait], [log_reuse_wait_desc], [is_date_correlation_on], [is_cdc_enabled], [is_encrypted], [is_honor_broker_priority_on], [replica_id], [group_database_id], [default_language_lcid], [default_language_name], [default_fulltext_language_lcid], [default_fulltext_language_name], [is_nested_triggers_on], [is_transform_noise_words_on], [two_digit_year_cutoff], [containment], [containment_desc], [target_recovery_time_in_seconds] ) SELECT [name], [database_id], [source_database_id], [owner_sid], [create_date], [compatibility_level], [collation_name], [user_access], [user_access_desc], [is_read_only], [is_auto_close_on], [is_auto_shrink_on], [state], [state_desc], [is_in_standby], [is_cleanly_shutdown], [is_supplemental_logging_enabled], [snapshot_isolation_state], [snapshot_isolation_state_desc], [is_read_committed_snapshot_on], [recovery_model], [recovery_model_desc], [page_verify_option], [page_verify_option_desc], [is_auto_create_stats_on], [is_auto_update_stats_on], [is_auto_update_stats_async_on], [is_ansi_null_default_on], [is_ansi_nulls_on], [is_ansi_padding_on], [is_ansi_warnings_on], [is_arithabort_on], [is_concat_null_yields_null_on], [is_numeric_roundabort_on], [is_quoted_identifier_on], [is_recursive_triggers_on], [is_cursor_close_on_commit_on], [is_local_cursor_default], [is_fulltext_enabled], [is_trustworthy_on], [is_db_chaining_on], [is_parameterization_forced], [is_master_key_encrypted_by_server], [is_published], [is_subscribed], [is_merge_published], [is_distributor], [is_sync_with_backup], [service_broker_guid], [is_broker_enabled], [log_reuse_wait], [log_reuse_wait_desc], [is_date_correlation_on], [is_cdc_enabled], [is_encrypted], [is_honor_broker_priority_on], [replica_id], [group_database_id], [default_language_lcid], [default_language_name], [default_fulltext_language_lcid], [default_fulltext_language_name], [is_nested_triggers_on], [is_transform_noise_words_on], [two_digit_year_cutoff], [containment], [containment_desc], [target_recovery_time_in_seconds] FROM [sys].[databases]; GO
Memeriksa Perubahan
Sekarang setelah kami menangkap informasi ini, bagaimana kami menemukan perubahan? Mengetahui bahwa mungkin ada beberapa pengaturan yang diubah, dan pada tanggal yang berbeda, kami memerlukan metode yang melihat setiap baris. Ini tidak sulit dilakukan, tetapi tidak menghasilkan kode tercantik. Untuk opsi server, tidak terlalu buruk:
;WITH [f] AS ( SELECT ROW_NUMBER() OVER (PARTITION BY [ConfigurationID] ORDER BY [CaptureDate] ASC) AS [RowNumber], [ConfigurationID] AS [ConfigurationID], [Name] AS [Name], [Value] AS [Value], [ValueInUse] AS [ValueInUse], [CaptureDate] AS [CaptureDate] FROM [Baselines].[dbo].[ConfigData] ) SELECT [f].[Name] AS [Setting], [f].[CaptureDate] AS [Date], [f].[Value] AS [Previous Value], [f].[ValueInUse] AS [Previous Value In Use], [n].[CaptureDate] AS [Date Changed], [n].[Value] AS [New Value], [n].[ValueInUse] AS [New Value In Use] FROM [f] LEFT OUTER JOIN [f] AS [n] ON [f].[ConfigurationID] = [n].[ConfigurationID] AND [f].[RowNumber] + 1 = [n].[RowNumber] WHERE ([f].[Value] <> [n].[Value] OR [f].[ValueInUse] <> [n].[ValueInUse]); GO
Mengubah Setelan Instance
Untuk opsi basis data, kueri ada dalam prosedur tersimpan (karena sangat berat), yang dapat Anda unduh di sini. Untuk menjalankan prosedur tersimpan:
EXEC dbo.usp_FindDBSettingChanges
Output akan mencantumkan database dan pengaturan yang diubah, serta tanggal:
Mengubah Setelan Basis Data
Anda dapat menjalankan kueri ini ketika masalah kinerja muncul, untuk memeriksa dengan cepat apakah ada pengaturan yang berubah, atau Anda bisa sedikit lebih proaktif dan menjalankannya secara teratur dalam pekerjaan terjadwal yang memberi tahu Anda jika ada yang berubah. Saya tidak menyertakan kode T-SQL untuk mengirim email menggunakan database mail jika ada perubahan, tetapi itu tidak akan sulit dilakukan berdasarkan kode yang disediakan di sini.
Menggunakan Performance Advisor
SQL Sentry Performance Advisor tidak melacak informasi ini secara default, tetapi Anda masih dapat menangkap informasi dalam database, kemudian meminta PA memeriksa untuk melihat apakah ada pengaturan yang berubah, dan memberi tahu Anda jika ada. Untuk mengatur ini, buat tabel SQLskills_ConfigData dan SQLskillsDBData dan atur tugas terjadwal untuk dimasukkan ke dalam tabel tersebut secara teratur. Di dalam klien SQL Sentry, siapkan Kondisi Kustom, seperti yang kami lakukan di postingan sebelumnya dalam seri ini, Pemeriksaan Kesehatan SQL Server Proaktif, Bagian 1:postingan Ruang Disk.
Dalam Kondisi Kustom, Anda memiliki dua opsi. Pertama, Anda bisa menjalankan kode yang disediakan yang memeriksa data historis untuk melihat apakah ada yang berubah (dan kemudian mengirim pemberitahuan jika demikian). Memeriksa data historis untuk perubahan adalah sesuatu yang akan Anda jalankan setiap hari, seperti yang Anda lakukan dengan Pekerjaan Agen. Atau, Anda bisa lebih proaktif dan membandingkan nilai yang berjalan saat ini dengan data terbaru secara lebih sering, mis. sekali dalam satu jam, untuk mencari perubahan. Kode contoh untuk memeriksa pengaturan saat ini untuk instance terhadap tangkapan terbaru:
;WITH [lc] AS ( SELECT ROW_NUMBER() OVER (PARTITION BY [ConfigurationID] ORDER BY [CaptureDate] ASC) AS [RowNumber], [ConfigurationID] AS [ConfigurationID], [Name] AS [Name], [Value] AS [Value], [ValueInUse] AS [ValueInUse], [CaptureDate] AS [CaptureDate] FROM [Baselines].[ConfigData] WHERE [CaptureDate] = (SELECT MAX([CaptureDate]) FROM [Baselines].[ConfigData]) ) SELECT [lc].[Name] AS [Setting], [lc].[CaptureDate] AS [Date], [lc].[Value] AS [Last Captured Value], [lc].[ValueInUse] AS [Last Captured Value In Use], CURRENT_TIMESTAMP AS [Current Time], [c].[Value] AS [Current Value], [c].[value_in_use] AS [Current Value In Use] FROM [sys].[configurations] AS [c] LEFT OUTER JOIN [lc] ON [lc].[ConfigurationID] = [c].[configuration_id] WHERE ([lc].[Value] <> [c].[Value] OR [lc].[ValueInUse] <> [c].[value_in_use]); GO
Ringkasan
Memeriksa opsi instans dan database sangat mudah dan jelas, dan dalam beberapa situasi, informasi historis ini dapat menghemat waktu Anda secara signifikan saat memecahkan masalah. Jika Anda tidak menangkap informasi ini di mana pun, saya mendorong Anda untuk memulai; selalu lebih baik untuk secara proaktif mencari masalah daripada bereaksi saat Anda memadamkan api dan berpotensi stres, tidak yakin apa yang menyebabkan masalah di lingkungan produksi Anda.