With this code, and an easy way to read the error logs where the DBCC CHECKDBresults will be written which I covered in Chapter 7, you will be comforted by the knowledge that you will no
Trang 1With this code, and an easy way to read the error logs where the DBCC CHECKDB
results will be written (which I covered in Chapter 7), you will be comforted by the knowledge that you will not let corruption seep into your data infrastructure and go unnoticed And that you can act thoughtfully to resolve the issue, once discovered
The custom query, in Listing 8.6, will iterate through all databases on a SQL Server instance, capture errors and mail the top error to you so that you can look further into the matter
CREATE TABLE #CheckDBTemp (
Error INT
, [Level] INT
, [State] INT
, MessageText NVARCHAR ( 1000 )
, RepairLevel NVARCHAR ( 1000 )
, [Status] INT
, [DBID] INT
, ObjectID INT
, IndexID INT
, PartitionID BIGINT
, AllocUnitID BIGINT
, [File] INT
, Page INT
, Slot INT
, RefFile INT
, RefPage INT
, RefSlot INT
, Allocation INT
)
Needed variables
DECLARE @TSQL NVARCHAR ( 1000 )
DECLARE @dbName NVARCHAR ( 100 )
DECLARE @dbErrorList NVARCHAR ( 1000 )
DECLARE @dbID INT
DECLARE @ErrorCount INT
DECLARE @EmailSubject NVARCHAR ( 255 )
DECLARE @ProfileName VARCHAR ( 100 )
DECLARE @EmailRecipient VARCHAR ( 255 )
Init variables
SET @dbID = 0
SET @dbErrorList = ''
SET @EmailSubject = 'Integrity Check Failure on '
CAST ( COALESCE ( @@SERVERNAME , 'Server Name Not Available' ) AS NVARCHAR )
SET @ProfileName = 'Notifications'
SET @EmailRecipient = 'rlandrum13@cox.net'
CYCLE THROUGH DATABASES
WHILE ( @@ROWCOUNT 0 )
Trang 28 – Finding data corruption
226
IF ( @dbID > 0 )
BEGIN
SET @TSQL = 'DBCC CHECKDB(''' @dbName + ''') WITH TABLERESULTS, PHYSICAL_ONLY, NO_INFOMSGS'
INSERT INTO #CheckDBTemp
EXEC ( @TSQL )
SELECT @ErrorCount = COUNT (*) FROM #CheckDBTemp
IF ( @ErrorCount > 0 )
BEGIN
SET @dbErrorList = @dbErrorList + CHAR ( 10 ) + CHAR ( 13 ) + 'Issue found on database : ' @dbName
SET @dbErrorList = @dbErrorList + CHAR ( 10 ) + CHAR ( 13 ) + ( Select Top 1 MessageText from #CheckDBTemp )
END
TRUNCATE TABLE #CheckDBTemp
END
IF SUBSTRING ( CONVERT ( varchar ( 50 ),
SERVERPROPERTY ( 'ProductVersion' )), 1 1 '8'
BEGIN
SELECT TOP 1 @dbName = name , @dbID = dbid
FROM sysdatabases WHERE dbid @dbID
AND name NOT IN 'tempdb' )
AND DATABASEPROPERTYEX ( name , 'Status' ) = 'Online' ORDER by dbid
END
ELSE
BEGIN
SELECT TOP 1 @dbName = name , @dbID = database_ID
FROM sys.databases WHERE database_ID > @dbID
AND name NOT IN 'tempdb' )
AND DATABASEPROPERTYEX ( name , 'Status' ) = 'Online' ORDER by database_ID
END
END
If errors were found
IF ( @dbErrorList <> '' )
BEGIN
IF SUBSTRING ( CONVERT ( varchar ( 50 ),
SERVERPROPERTY ( 'ProductVersion' )), 1 1 '8'
BEGIN
EXEC master xp_sendmail @recipients = @EmailRecipient ,
@subject = @EmailSubject , @message = @dbErrorList
END
ELSE
BEGIN
Trang 3EXEC msdb sp_send_dbmail @profile_name = @ProfileName ,
@recipients = @EmailRecipient , @subject = @EmailSubject , @body
= @dbErrorList , @importance = 'High'
END
END
DROP TABLE #CheckDBTemp
Listing 8.6: A script for seeking out and reporting database corruption
You will notice that the code uses a DBCC CHECKDB option that I've not previously covered, and that is WITH TABLERESULTS As the name suggests, it causes the results to be returned in table format This option is not covered in Books Online, but is highly useful for automating error checking via SQL Agent Jobs or custom code
This code can easily be modified to return an email reporting that all databases except NEO are in good shape It might soften the blow somewhat to know that of
20 databases only one is corrupt I know it would help me somewhat In any event, when corruption occurs you are going to receive the mail, seen in Figure 8.14, which is truly the monster that wakes you up in the middle of the night in a cold sweat
Trang 48 – Finding data corruption
228
In this mail, I can see the ObjectID, the IndexID and the corrupted page, as well
as the database name This should be enough to go on for further investigation with the newfound tools, DBCC PAGE, DBCC INDID and DBCC CHECKDB, with repair options Or, it should be a wakeup call to the fact that you might have to restore from a good backup
Summary
In this final chapter, I have discussed how to corrupt a database and delved into several undocumented DBCC options that will assist you when corruption happens to your data Notice I said "when" I have only touched the surface of the topic here by showing, at a very high level, how to translate pages to hexadecimal values and understand how to correlate the results of various DBCC commands, while troubleshooting corruption issues
I cannot stress enough that having a good backup plan is the most important task for the DBA While I did not cover backups and restores in great depth in this chapter (an entire book can be written on this topic alone), I have at least shown the best reason to have such a good backup as part of your overall high availability and disaster recovery plan A corrupt database will indeed be a disaster and could incur much downtime You do not want to have to go to your boss, or your bosses' boss, and tell them that you have lost data irrevocably If you do, you might as well pull your resume out from whatever disk drive it may be on (assuming that's not corrupt as well) and update it
There is often panic when discovering any level of corruption in your databases Without verified backups and some basic troubleshooting tips, there is no safe place to hide when the monster rears up All you can do is perform a repair, potentially allowing data loss for hundreds of data pages, and then duck away into the nearest cubicle, which if it was yours will soon be empty
If you do have good backups and can repair the damage without data loss, then that cubicle may one day turn into an executive office where the wall-to-wall tinted windows reveal the flowing brook outside, where no monsters live
The End