A Read of the File Succeeded After Failing (Error 825, the Read-Retry Warning)

🚨Part of the SQL Server Errors series, the exact messages and what actually causes them.

Msg 825  ·  Level 10  ·  State 2
A read of the file ‘D:\Data\YourDb.mdf’ at offset 0x00000c46e58000 succeeded after failing 1 time(s) with error: incorrect checksum (expected: 0x2f8a1b3c; actual: 0x9d4e7a11). Additional messages in the SQL Server error log and system event log may provide more detail. Msg 825, Level 10, State 2
Treat it as a disk incident that has not happened yet. Prove the backups restore, run CHECKDB, and take the message to whoever owns the storage; the retry that saved you this time is not a fix.

Read the first line again. It succeeded. That is why this error is dangerous.

Severity 10 is informational, so it raises no alert, fails no job, and returns nothing to the application. Everything carries on working. Meanwhile SQL Server has just told you that your storage returned bad data and only got it right on a retry.

825 is the polite warning before 823 and 824, which are the ones that take a database offline and end with you reaching for backups. On most systems it is the only advance notice you get, and on most systems nobody is listening.


What It Actually Means

SQL Server asked the storage layer for a page. The read came back wrong, either failing outright or returning data whose checksum did not match. SQL Server retried, up to four times, and one of the retries worked.

The data is fine right now. The hardware or the path to it is not.

This is not a SQL Server problem and no amount of DBCC will fix it. Something between the buffer pool and the platter is intermittently wrong: a failing disk, a controller, a driver, a cable, a flaky HBA, a SAN path, or a hypervisor storage layer.


Find Out Whether It Has Happened Before

EXEC xp_readerrorlog 0, 1, N'succeeded after failing', NULL, NULL, NULL, N'DESC';

Run it against the older logs as well, because this is exactly the message that has been quietly recurring for weeks:

DECLARE @i INT = 0;
WHILE @i < 6
BEGIN
    BEGIN TRY
        EXEC xp_readerrorlog @i, 1, N'succeeded after failing';
    END TRY
    BEGIN CATCH
    END CATCH
    SET @i += 1;
END

A single occurrence is worth investigating. A pattern is a failing device, and the interval between occurrences shortening is the thing to watch for.

Check whether the same window shows anything worse:

EXEC xp_readerrorlog 0, 1, N'823';
EXEC xp_readerrorlog 0, 1, N'824';

Check the Suspect Pages Table

SQL Server records pages it had trouble with, and this table is almost never looked at:

SELECT  DB_NAME(database_id) AS database_name,
        file_id,
        page_id,
        event_type,     -- 1 = 823/824 error, 2 = bad checksum, 3 = torn page,
                        -- 4 = restored, 5 = repaired, 7 = deallocated
        error_count,
        last_update_date
FROM    msdb.dbo.suspect_pages
ORDER   BY last_update_date DESC;

Any row here deserves attention. An empty table is good news; rows with event_type 2 or 3 mean real corruption was seen, whether or not a retry rescued it.


What To Do

In this order, because the order matters:

  • 1. Check your backups are good and restorable. Not that they exist, that they restore. Do this before anything else, because everything after this can make things worse if it turns out you need them.
  • 2. Run DBCC CHECKDB with PHYSICAL_ONLY first, which is much faster and catches exactly this class of problem:
    DBCC CHECKDB (YourDb) WITH PHYSICAL_ONLY, NO_INFOMSGS;
    Then a full DBCC CHECKDB when you have a window, if the quick one comes back clean.
  • 3. Take it to whoever owns the storage with the offsets and timestamps from the error log. This is a hardware conversation and the log entries are the evidence.
  • 4. Check the Windows system event log in the same window. Disk, storage driver and HBA errors there confirm it and give the storage team something to act on.

Do not run REPAIR_ALLOW_DATA_LOSS because of an 825. Nothing is broken yet. That command is for corruption you have confirmed and cannot restore around, and it does exactly what it says.


Stopping It Being Missed

  • Alert on 825 explicitly. It is severity 10, so no default alert catches it. This is the single most valuable thing in this post: an Agent alert on message 825 turns a silent warning into a phone call while there is still time.
  • Alert on 823 and 824 as well, which most people do, and check suspect_pages on a schedule.
  • Keep PAGE_VERIFY CHECKSUM on. Without it SQL Server has no way to notice a bad read at all:
    SELECT name, page_verify_option_desc
    FROM sys.databases;
    Anything other than CHECKSUM means these errors cannot be detected on that database.
  • Run DBCC CHECKDB regularly. Not because it prevents corruption, but because it dates it. A clean check last week tells you how far back you can safely restore.

Common Questions

It says it succeeded, so is there a problem?
Yes. The data is fine right now and the hardware is not. SQL Server had to retry a read because the storage returned bad data. This is the warning that arrives before 823 and 824, which are the ones that take a database offline.
Why did nothing alert me?
Severity 10 is informational, so no default alert fires, no job fails and the application sees nothing. Setting an Agent alert on message 825 is the single most valuable thing in this post.
Should I run REPAIR_ALLOW_DATA_LOSS?
No. Nothing is broken yet. That command is for confirmed corruption you cannot restore around, and it does exactly what its name says. Check your backups restore, run DBCC CHECKDB WITH PHYSICAL_ONLY, and take it to whoever owns the storage.

Related Scripts

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *