WHEN SERVERPROPERTY 'EditionID' = 4161255391 THEN 'Express Edition with Advanced Services' END AS ProductEdition, CASE WHEN CONVERT CHAR 100, SERVERPROPERTY 'IsClustered' 1 THEN '
Trang 1WHEN SERVERPROPERTY( 'EditionID' ) = 4161255391 THEN 'Express Edition with Advanced Services' END AS ProductEdition,
CASE WHEN CONVERT( CHAR (100),
SERVERPROPERTY( 'IsClustered' )) 1
THEN 'Clustered'
WHEN SERVERPROPERTY( 'IsClustered' ) = 0
THEN 'Not Clustered' WHEN SERVERPROPERTY( 'IsClustered' ) = NULL
THEN 'Error'
END AS IsClustered,
CASE WHEN CONVERT( CHAR (100),
SERVERPROPERTY( 'IsFullTextInstalled' )) 1
THEN 'Full-text is installed'
WHEN SERVERPROPERTY( 'IsFullTextInstalled' ) = 0 THEN 'Full-text is not installed'
WHEN SERVERPROPERTY( 'IsFullTextInstalled' ) = NULL
THEN 'Error'
END AS IsFullTextInstalled,
CONVERT( CHAR (100), SERVERPROPERTY( 'SqlCharSet' ))
AS SqlCharSet, CONVERT( CHAR (100), SERVERPROPERTY( 'SqlCharSetName' ))
AS SqlCharSetName, CONVERT( CHAR (100), SERVERPROPERTY( 'SqlSortOrder' ))
AS SqlSortOrderID, CONVERT( CHAR (100), SERVERPROPERTY( 'SqlSortOrderName' ))
AS SqlSortOrderName
ORDER BY CONVERT( CHAR (100), SERVERPROPERTY( 'Servername' ))
Listing 2.1: Server information
As you can see, it's a pretty simple script that makes liberal use of the
SERVERPROPERTY function to return the required data
Figure 2.1: Collecting server information
Trang 2NOTE
All of the various properties of the SERVERPROPERTY function can be found in Books Online or MSDN, see http://msdn.microsoft.com/en-us/library/ms174396.aspx
If you were to run this query against one of your SQL Servers, you'd see results similar to those shown in Figure 2.1, all of which will be useful in your daily reporting of your infrastructure
One piece of information that this script does not return is the location of the server There is no way to glean the location information from a query Some things, at present, still have to be manually gathered
Database management
It is obviously important that DBAs know what databases are on each of their servers While DBAs may not be intimately familiar with every database schema
on every SQL Server, it is essential that they are aware of the existence of every database, and at least understand the basic characteristics of each, such as what server they are on, what size they are and where on disk they are located
You can also gather the information you need to monitor the growth of the data and log files for each database, or answer questions such as "where are the system database files located?" This question brings up the interesting topic of implementing standards across all of your servers Are the data files for each server stored on the correct, predetermined data drive? The log files on the correct log drive? Are naming conventions consistently enforced? Is each database using the correct default recovery model (e.g SIMPLE) unless specified otherwise? You may find that the answer is, generally, "no" It is an unfortunate reality that, often, a DBA will inherit an infrastructure whereby a hodge-podge of different standards have been set and only erratically imposed by a variety of former DBAs However, once you've got all of this data stored in a central repository, for every server, you can quickly report on how well your current standards have been enforced, and can start the job of pulling the "non-standard" ones into shape And then, who knows, if you can stay in the position long enough, say ten years, you may actually get to see an infrastructure that properly adheres to all the standards you set forth
To gather this database management information, you will need to run the same two queries on each SQL 2000, 2005 and 2008 instance The first of these queries
is shown in Listing 2.2 It makes use of the sp_msforeachdb system stored procedure, which issues the same query for each database on a server, and saves
Trang 3you the time of writing your own cursor or set-based query to iterate through each database I create a temp table, HoldforEachDB and then populate that table with the results from each database In this way, I have one result set for all databases
on the server, instead of individual result sets for each database, which would have otherwise been the case Also, since I know that I will ultimately want to get this information from SSIS, and into a central DBA repository, having the temp table pre-defined is ideal
IF EXISTS SELECT *
FROM tempdb.dbo.sysobjects
WHERE id =
OBJECT_ID( '[tempdb].[dbo].[HoldforEachDB]' ) )
DROP TABLE [tempdb].[dbo].[HoldforEachDB] ;
CREATE TABLE [tempdb].[dbo].[HoldforEachDB]
(
[Server] [nvarchar](128) COLLATE
SQL_Latin1_General_CP1_CI_AS
NULL,
[DatabaseName] [nvarchar](128) COLLATE
SQL_Latin1_General_CP1_CI_AS
NOT NULL,
[Size] [int] NOT NULL,
[File_Status] [int] NULL,
[Name] [nvarchar](128) COLLATE
SQL_Latin1_General_CP1_CI_AS
NOT NULL,
[Filename] [nvarchar](260) COLLATE
SQL_Latin1_General_CP1_CI_AS
NOT NULL,
[Status] [nvarchar](128) COLLATE
SQL_Latin1_General_CP1_CI_AS
NULL,
[Updateability] [nvarchar](128) COLLATE
SQL_Latin1_General_CP1_CI_AS
NULL,
[User_Access] [nvarchar](128) COLLATE
SQL_Latin1_General_CP1_CI_AS
NULL,
[Recovery] [nvarchar](128) COLLATE
SQL_Latin1_General_CP1_CI_AS
NULL
)
ON [PRIMARY]
INSERT INTO [tempdb].[dbo].[HoldforEachDB]
EXEC sp_MSforeachdb 'SELECT CONVERT(char(100),
SERVERPROPERTY(''Servername'')) AS Server,
''?'' as DatabaseName,[?] sysfiles.size, [?] sysfiles.status, [?] sysfiles.name,
[?] sysfiles.filename,convert(sysname,DatabasePropertyEx(''?'' ,''Status'')) as Status,
Trang 4convert(sysname,DatabasePropertyEx(''?'',''Updateability'')) as Updateability,
convert(sysname,DatabasePropertyEx(''?'',''UserAccess'')) as User_Access,
convert(sysname,DatabasePropertyEx(''?'',''Recovery'')) as Recovery From [?] sysfiles '
Listing 2.2: Placing database information into a temporary table
The second query, shown in Listing 2.3, simply selects from the HoldforEachDB
temporary table
SELECT [Server]
,[DatabaseName]
,[Size]
,[File_Status]
,[Name]
,[Filename]
,[Status]
,[Updateability]
,[User_Access]
,[Recovery]
FROM [tempdb].[dbo].[HoldforEachDB]
Listing 2.3: Selecting data from the temporary table, HoldForEachDB
The output of this query can be seen in Figure 2.2, which displays the server name, as well as the database name, size, filename and recovery model
Figure 2.2: Output of database info query
Trang 5Database backups
Having backup information is critical for the DBA, especially when working with
a large infrastructure Knowing where the full, differential or log backups are located is more than helpful; it is essential This type of information can easily be gathered directly from the MSDB database, which has not changed substantially from SQL Server 2000 to 2008 Listing 2.4 shows the driving query for gathering from MSDB the vital database backup information that you need for each server, including information such as backup start date, end data and size Notice, in the WHERE clause, that this query actually retrieves 30 days worth of history
SELECT CONVERT( char (100), SERVERPROPERTY( 'Servername' ))
AS Server ,
msdb.dbo.backupmediafamily.logical_device_name,
msdb.dbo.backupmediafamily.physical_device_name,
msdb.dbo.backupset.expiration_date,
msdb.dbo.backupset.name,
msdb.dbo.backupset.description,
msdb.dbo.backupset.user_name,
msdb.dbo.backupset.backup_start_date,
msdb.dbo.backupset.backup_finish_date,
CASE msdb backupset.type
WHEN 'D' THEN 'Database'
WHEN 'L' THEN 'Log'
END AS backup_type,
msdb.dbo.backupset.backup_size,
msdb.dbo.backupset.database_name,
msdb.dbo.backupset.server_name AS Source_Server
FROM msdb.dbo.backupmediafamily
INNER JOIN msdb.dbo.backupset ON
msdb.dbo.backupmediafamily.media_set_id =
msdb.dbo.backupset.media_set_id
WHERE ( CONVERT( datetime ,
msdb.dbo.backupset.backup_start_date, 102) >= GETDATE()
- 30 )
Listing 2.4: Query to gather database backup information
Figure 2.3 shows the output of this backup history query
Figure 2.3: Gathering database backup information