Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

We have a SQL 2000 DB. The server crashed due to Raid array failure. Now when we run DBCC CHECKDB, we get an error that there are 27 consistency errors in 9 pages.

When we run DBCC PAGE on these pages, we get this:

Msg 8939, Level 16, State 106, Line 1
Table error: Object ID 1397580017, index ID 2, page (1:8404521). Test (m_freeCnt == freeCnt) failed. Values are 2 and 19.
Msg 8939, Level 16, State 108, Line 1
Table error: Object ID 1397580017, index ID 2, page (1:8404521). Test (emptySlotCnt == 0) failed. Values are 1 and 0.

Since the indicated index is non-clustered and is created by a unique constarint that includes 2 columns, we tried dropping and recreating the index. This resulted in the following error:

CREATE UNIQUE INDEX terminated because a duplicate key was found for index ID 2. Most significant primary key is '3280'. 
The statement has been terminated. 

However running

Select var_id,result_on
from tests
group by var_id,result_on
having count(*)>1

returns 0 rows.

Here is what we are planning to do:

  • Restore a pre-server crash copy of the DB and run DBCC CHECKDB
  • If that returns clean, then restore again with no recovery
  • Apply all subequent TLOG backups
  • Stop production app, take a tail log backup and apply that too
  • Drop prod DB and rename the freshly restored DB to make it prod
  • Start prod app

Could someone please punch holes in this approach? Maybe, suggest a different approach? What we need is minimum downtime.

SQL 2000 DB Size 94 GB The table that has corrupt pages has 460 Million+ rows of data

Thanks for the help.


share|improve this question

migrated from Feb 7 '10 at 2:04

This question came from our site for professional and enthusiast programmers.

I like your approach. Makes sense to me. Perhaps keep the damaged database along side, as insurance... – user24161 Feb 5 '10 at 19:48
Also, when things settle down, plan your 2008 or 2008 upgrade :-) – user24161 Feb 5 '10 at 19:50
(that is, 2005 or 2008 upgrade) – user24161 Feb 5 '10 at 19:51
+1 for having a valid and very suitable recovery plan – Andrew Feb 5 '10 at 20:29

Your recovery solution is the text book way to proceed. Assuming you have appropriate backups and provided you can backup the transaction log for the corrupt database, then your strategy is the text book one to implement.

Before proceeding however have you considered the possibility of recreating solely the affected table?

Sometimes you can get away with creating an exact copy of the affected table by doing a

select *
into NewTableFromOld
from DamagedTable

Then just drop/swap the damaged table with the new, remembering to add appropriate constraints and indexes.

share|improve this answer
Thanks for the response. You approach looks good, but the concern is, considering that the table has 461 million rows of data, what would be the impact on production when I do a select *? Wouldn't that aquire a lock and hit performance? – Raj Feb 6 '10 at 7:24
Not if you use the with (nolock) query hint no. However, you may wish to validate that nothing has changed between source and target table whilst you took the copy. This would likely be required during the table build anyway though if you did not stop the app from making changes. There will be disk performance overhead in such an operation. – John Sansom Feb 6 '10 at 7:32
Personally I would try this approach first, you can do it with the nolock option for testing, you can check the time required also. If it works like it should, I would then put the db in single user mode while doing it again, to make sure that no changes happen while the process is running. Downtime will be much shorter during this approach, if it works. – baldy Mar 17 '10 at 12:13
If you are going to do this, I would recommend creating the table first (by scripting out the original table). Then use "INSERT INTO newTable SELECT" vs the "SELECT INTO". You can run into performance issues with a "SELECT INTO". – SQL3D Jan 14 '11 at 20:45

I'd try bulking out the data to file first and then bulk it back in to a new table. SELECT INTO isn't appropriate (IMO) for that number of records...

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.