Monthly Archives: November 2011

Error Fix: Msg 605 Attempt to fetch logical page (3:1307866) in database 6 failed. It belongs to allocation unit 72057594113359872 not to 72057594113490944

Msg 605, Level 21, State 3, Line 1
Attempt to fetch logical page (3:1307866) in database 6 failed. It belongs to allocation unit 72057594113359872 not to 72057594113490944.
Or
Msg 21, Level 21, State 1, Line 1
Warning: Fatal error 605 occurred at OCT  31 2011  6:08AM. Note the error and time, and contact your system administrator.
This error comes in red color is disguise, if you login with any user which is not sysadmin type user, you will see this kind of error in corruption of page(s), if you login with SA, Administrator or and other SysAdmin login, you will not see error comes in red color but the descriptive error given in the title
There was a festival holidays in our Indian office from 26thto 28th OCT 2011 (Wed/Friday) so obviously I was out of town and back after 5 days on 31st OCT 2011. As soon as I come to the office and checked few of my email, I suddenly get complain that few pages in our software are throwing an error so I picked up the query which was there in those pages along with the same parameter they were providing and found the error given above.
As soon as I read this error, I came to know that there is a page corruption in database.  It may be due to heavy snow fall in NJ in October, they have got power failure there from few days and tried to keep the server up and running via power generator. As soon as Power Generator’s fuel get finished, everything gets down and after refuel, they starts everything again. I came to know this as soon as I come back from holiday. I think this is the Indian New Year gift to me.
I tried to gather some more information about the data file and page number given in error message with DBCC PAGE command.
dbcc traceon(3604)
dbcc page(‘MyDatabaseName’,3,1307866,3)

dbcc traceoff(3604)

You can use option 0,1,2,3 as the last parameter (bold 3) of DBCC PAGE command.
So now I have two options.
1.)    Restore that page from full Database backup
2.)    Try DBCC commands and if needed, allow data loss
I HIGHLY RECOMMEND to go for 1st option but if you are out of luck and don’t have last full backup, you must have to go for second way.
I have restored page from my last full database backup with below given TSQL.
RESTORE DATABASE MyDatabaseName
PAGE = ‘3:1307866’
FROM DISK = ‘D:\MyDatabaseName.bak’
WITH NORECOVERY
Now, let us talk about second option if you don’t have full backup of your database. Use DBCC CHECKDB command.
–checking database’s integrity and won’t show so many informational message,
–it will only shows error messages and warnings.
DBCC CHECKDB(‘MyDatabaseName’) WITH NO_INFOMSGS
Once you execute above command, it will recommend you repair level. it may recommend REPAIR_REBUILD if you really lucky but if you will see repair level REPAIR_ALLOW_DATA_LOSS, you have to be ready to lose some of your data.
You may use either of the below given command based on the Repair Level you have been suggested.
1.)
ALTER DATABASE MyDatabaseName SETSINGLE_USER
GO
DBCC CHECKDB(‘MyDatabaseName’, REPAIR_REBUILD)
GO
ALTER database MyDatabaseName SETMULTI_USER
GO
2.)
ALTER DATABASE MyDatabaseName SETSINGLE_USER
GO
DBCC CHECKDB(‘MyDatabaseName’, REPAIR_ALLOW_DATA_LOSS)
GO
ALTER database MyDatabaseName SETMULTI_USER
GO
Moral of the story is, always have FULL recovery model for your database and schedule full/ transaction/ differential backup policy. This is a MUST DO for any DBAs. You never know, when will you need it!!!!
Reference: Ritesh Shah
 
http://www.sqlhub.com
Note: Microsoft Books online is a default reference of all articles but examples and explanations prepared by Ritesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile
Microsoft SQL Server Blog. Fight the fear of SQL with SQLHub.com. Founder is Ritesh Shah

Playing with OPTION KEEPFIXED PLAN hint in SQL Server

My previous article was on Compilation & Recompilation of Stored Procedure. After reading that article, two of my reader sent me an email about more clarification on some terminology and that is the base of writing this article.
Actually SQL Server Query Optimizer is really one of the smart tools which used to find or generate best execution plan for query or stored procedure and make the task easy for DBA. Basically it uses Cost Based Optimizer (CBO) to do this task, even sometime feels to have specific Execution Plan for query so Microsoft have provided many different hints at different level.
Query Optimizer (QO) used to save execution plan when it compiles Stored Procedure first time and use the same execution plan when the same stored procedure is being used again so that you can get rid of overhead of generating execution plan again and again.
When index statistics changes heavily, QO used to recompile the statement to get best plan for your stored procedure but if you are sure that the existing Plan would works fine than one should go for OPTION KEEPFIXED PLAN for that statement so that you can save your resources and boost up performance.
I will demonstrate this with few queries run in SQL Server Management Studio (SSMS) and capture the results in Profiler.
I will select following Events in Profiler while creating new Trace for my server.
Stored Procedure
  • SP:Completed
  • SP:Recompile
  • SP:smtpCompleted
  • SP:smtpStarting

 

Now execute following TSQL in your SSMS.
–create one database which you can delete after running this example
create database SQLHub
GO
USE SQLHub
GO
–if orders table is already there. you can delete it than create new one with name “Orders”
IF OBJECT_ID(‘orders’, ‘U’) IS NOT NULL BEGIN
      DROP TABLE orders
END
GO
–creating table
CREATE TABLE orders(OrderID INT IDENTITY, OrderDate DATETIME, Amount MONEY, Refno INT)
GO
–creating nonclustered index
CREATE NONCLUSTERED INDEXIDX_ORD ON Orders(amount)
GO
–inserting only 1 record in our table
INSERT INTO orders VALUES(GETDATE(),1001,111)
GO
–creating SP which will SELECT all records from Orders table where Amount is 1001
CREATE PROC spGet_ord
AS
SELECT * FROM orders WHERE Amount=1001
GO
–execute SP
exec spGet_ord
GO
If you will see in profiler than you would get following event captured
Now, make change in Index statistics by inserting so many records in table so that we can test the effect in profiler after executing SP again.
–inserting 50000 fack rows into table
INSERT INTO orders(OrderDate, Amount, Refno)
SELECT TOP 50000
      DATEADD(minute, ABS(a.object_id % 50000 ), CAST(‘2010-02-01’ AS DATETIME)),
      ABS(a.object_id % 10),
      CAST(ABS(a.object_id) AS VARCHAR)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
GO
–execute SP again
exec spGet_ord
GO
Now, if you see the profiler, you will see “SP:Recompile” event as your statistics are updated so it need recompilation of statement. If you again few more thousands record in same table and execute the same SP again, you will see recompilation again.
Now, after droping table and SP, we will make one small change in Stored Procedure and will use “KEEPFIXED PLAN” hint so that we can avoid recompilation.
drop proc spGet_ord
GO
drop table orders
go
–creating table
CREATE TABLE orders(OrderID INT IDENTITY, OrderDate DATETIME, Amount MONEY, Refno INT)
GO
CREATE NONCLUSTERED INDEXIDX_ORD ON Orders(amount)
GO
INSERT INTO orders VALUES(GETDATE(),1001,111)
GO
CREATE PROC spGet_ord
AS
SELECT * FROM orders WHERE Amount=1001
–adding below statement other than that, same code as previous SP
OPTION (KEEPFIXED PLAN);
GO
exec spGet_ord
GO
After recreating table along with fresh records, we are going to see what happened while executing SP in above statement.
Since our table now has only 1 record so it is time to change statistics with bulk insert as follows again.
–inserting 100000 fack rows into table (BTW, thank to Jacob Sebastian, copy in INSERT script from one of his demo to generate big table)
INSERT INTO orders(OrderDate, Amount, Refno)
SELECT TOP 50000
      DATEADD(minute, ABS(a.object_id % 50000 ), CAST(‘2010-02-01’ AS DATETIME)),
      ABS(a.object_id % 10),
      CAST(ABS(a.object_id) AS VARCHAR)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
GO
exec spGet_ord
GO
–if you wish, you can uncomment below code and delete SQLHub database
–use master
–go
–drop database sqlhub
Here is the screen capture of Profiler which doesn’t show Recompilation.

 

You can even add few more thousands of rows and execute SP again, you won’t get recompilation.
Reference: Ritesh Shah
 
http://www.sqlhub.com
Note: Microsoft Books online is a default reference of all articles but examples and explanations prepared by Ritesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile
Microsoft SQL Server Blog. Fight the fear of SQL with SQLHub.com. Founder is Ritesh Shah