1. Trang chủ
  2. » Công Nghệ Thông Tin

SQL Server Tacklebox- P45 docx

5 78 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 227,68 KB

Nội dung

8 – Finding data corruption 220 Figure 8.11: Missing data after DBCC CHECKDB Repair_Allow_Data_Loss. These rows should be easily recovered if you have a good backup. You have a good backup, right? Right? Assuming you do, then you are faced with the task of restoring from backup to another database, like NEO2, and syncing the two tables for the missing rows. Syncing the two tables can be accomplished with a simple INSERT INTO statement, like that shown in Listing 8.4. 8 – Finding data corruption 221 INSERT INTO NEO ONE ( NEOID, NEOTEXT ) SELECT NEOID, NEOTEXT FROM NEO2 ONE WHERE NEOID NOT IN ( SELECT NEOID FROM NEO ONE ) Listing 8.4: Syncing two tables to recover lost data rows. In this "controlled example", the fix is fairly simple. Other scenarios, with much higher levels of corruption, may require you to turn to other measures to get the data back, after repairing with data loss. These means will almost always involve a restore of the database from backup, which is why I impress again the importance of a solid, verified and well documented database backup policy. Corruption on non-clustered indexes I noted earlier that corruption of a non-clustered index is much easier to deal with than corruption of an actual data page, as these indexes are just "redundancies" of the actual data and can be easily rebuilt. However, it would be interesting to prove this point. I'll use the same Hexadecimal editor technique to corrupt the non- clustered index, and not the data, and see what the outcome would be. One indicator of whether the corruption is on an index or a table is the IndexID provided with the DBCC output. For our ONE heap table, I noted (in Listing 8.3) that the IndexID was 0 as there were no indexes defined for the table. An IndexID of 1 means a clustered index and a value of 2-250 indicates a non- clustered index. For the sake of brevity, let's assume that I have performed the necessary repair on the NEOID column and created a non-clustered index on the ONE table, for the NEOID column. First, I need to find out the page value of the index I defined for the ONE table. I will then plug this page of the non-clustered index into DBCC PAGE so that I know, again, exactly what data to modify to simulate index corruption, instead of data page corruption of the heap. To retrieve the page value of the index, I can use another DBCC command, call it undocumented again, DBCC INDID. The syntax for this command is: DBCC INDID (DBID, TABLEID,-1) So, to execute this for my newly-indexed ONE table, the command will be: DBCC ind(23, 2121058592, -1) 8 – Finding data corruption 222 The results reveal several IndexIDs, mostly zero, along with several IndexID values of 2, indicating a non-clustered index. Notice in Figure 8.11 the IndexID of 2 and the associated page of that index, 180. Figure 8.12: Finding the page of the new non-clustered index. I can now run DBCC PAGE again, plugging in this page information: DBCC TRACEON (3604); GO DBCC PAGE (NEO,1,180,3) GO The results look a lot different than when looking at a data page. I see returned the Hexadecimal value ( HEAP RID) that represents each row in the index for the page interrogated, as shown in Figure 8.12. 8 – Finding data corruption 223 Figure 8.13: Looking at the non-clustered index for the ONE table with DBCC PAGE. I used the Hex editor again to modify, or zero out, the HEAP RID, and once again this does indeed corrupt the database in much the same way as changing an actual data page. However, there is one major difference: this time, when I run DBCC CHECKDB('neo') WITH PHYSICAL_ONLY, the IndexID of the corrupt object is reported as "2" i.e. a non-clustered index. 8 – Finding data corruption 224 Armed with this knowledge, I have open to me options for repairing the damage, other than restoring from backup, or running DBCC CHECKDB with REPAIR_ALLOW_DATA_LOSS, with the potential loss of data that this entails. I can simply drop and recreate the non-clustered index using the code in Listing 8.5. USE [NEO] GO IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[ONE]') AND name = N'NEO_ID_NC') DROP INDEX [NEO_ID_NC] ON [dbo].[ONE] WITH ( ONLINE = OFF ) GO USE [NEO] GO CREATE NONCLUSTERED INDEX [NEO_ID_NC] ON [dbo].[ONE] ( [NEOID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO Listing 8.5: Drop and recreate corrupt non-clustered index. Now that I have delved somewhat into corrupting, finding and fixing some problems, let's turn now to the discovery process. Seeking out corruption What is the best way for you to find out that you have corruption on your databases, before it propagates through numerous backups and causes bigger issues than it need do? One option is to set up regular integrity checks using Maintenance Plans, which are useful, and certainly better than not having any integrity checks at all. However, I enjoy the level of control and flexibility I have when building custom scripts to perform the same functions as the maintenance plans. As such, rather than delve into maintenance plans, I will instead share with you a script that I use to iterate through each database, including system databases, and report on any errors returned by DBCC CHECKDB.

Ngày đăng: 04/07/2014, 23:20