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

SQL Server Tacklebox- P45 docx

5 78 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

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 jus

Trang 1

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

Trang 2

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 , - )

Trang 3

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 , , 180 , )

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

Trang 4

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

Trang 5

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 ( '[dbo].[ONE]' )

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

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN