SQL Server 診斷偵測到因為讀取過期或寫入遺失而未回報的 I/O 問題

本文說明 SQL Server 診斷如何協助偵測因讀取過期或寫入遺失而發生的未回報輸入或輸出問題。

原始產品版本: SQL S
原始 KB 編號: 826433

徵狀

如果操作系統、驅動程式或硬體問題導致 I/O 路徑中的寫入或讀取條件遺失,您可能會在 SQL Server 中看到數據完整性相關的錯誤訊息,例如錯誤 605、823、3448 和 3456。 您可能會收到類似下列範例的錯誤訊息:

2003-07-24 16:43:04.57 spid63 Getpage: bstat=0x9, sstat=0x800, cache
2003-07-24 16:43:04.57 spid63 pageno is/should be: objid is/should be:
2003-07-24 16:43:04.57 spid63 (1:7040966)/(1:7040966) 2093354622/2039782424
2003-07-24 16:43:04.57 spid63 ... IAM indicates that page is allocated to this object
2003-07-24 16:52:37.67 spid63 Error: 605, Severity: 21, State: 1
2003-07-24 16:52:37.67 spid63 Attempt to fetch logical page (1:7040966) in database 'pubs' belongs to object 'authors', not to object 'titles'..
2003-07-24 16:52:40.99 spid63 Error: 3448, Severity: 21, State: 1
2003-07-24 16:52:40.99 spid63 Could not undo log record (63361:16876:181), for transaction ID (0:159696956), on page (1:7040977), database 'pubs' (database ID 12). Page information: LSN = (63192:958360:10), type = 2. Log information: OpCode = 2, context 1..
2003-07-09 14:31:35.92 spid66 Error: 823, Severity: 24, State: 2
2003-07-09 14:31:35.92 spid66 I/O error (bad page ID) detected during read at offset 0x00000016774000 in file 'h:\sql\MSSQL\data\tempdb.mdf'..
2010-02-06 15:57:24.14 spid17s Error: 3456, Severity: 21, State: 1.
2010-02-06 15:57:24.14 spid17s Could not redo log record (58997:5252:28), for transaction ID (0:109000187), on page (1:480946), database 'MyDatabase' (database ID 17). Page: LSN = (58997:5234:17), type = 3. Log: OpCode = 2, context 5, PrevPageLSN: (58997:5243:17). Restore from a backup of the database, or repair the database.

SQL Server 中的新 I/O 診斷功能

從 SQL Server 2000 Service Pack 4 開始,SQL Server 導入了新的 I/O 診斷功能,而這些診斷自此之後便已成為產品的一部分。 這些功能旨在協助偵測外部 I/O 相關問題,以及針對 徵兆 一節中所述的錯誤訊息進行疑難解答。

如果您收到 [兆] 區段中所列的任何錯誤訊息,但事件並未說明這些錯誤訊息,例如實體磁碟驅動器故障,請檢閱 SQL Server、操作系統、驅動程式和硬體的任何已知問題。 診斷會嘗試提供下列兩個條件的相關信息:

  • 遺失寫入:成功呼叫 WriteFile API,但即使 SQL Server 得知寫入成功,操作系統、驅動程式或快取控制器也不會正確地將數據排清至實體媒體。

  • 過時的讀取:成功呼叫 ReadFile API,但操作系統、驅動程式或快取控制器不正確地傳回舊版的數據。

為了說明,Microsoft 已確認 WriteFile API 呼叫傳回成功狀態,但相同數據區塊的立即成功讀取會傳回較舊的數據,包括可能儲存在硬體讀取快取中的數據。 有時候,此問題會因為讀取快取問題而發生。 在其他情況下,寫入數據永遠不會寫入實體磁碟。

如何啟用診斷

在 SQL Server 2017 和更新版本中,預設會啟用此診斷功能。 在 SQL Server 2016 和舊版中,只能使用追蹤旗標 818 來啟用這些診斷。 您可以指定追蹤旗標 818 作為 SQL Server 實體的啟動參數 -T818,也可以執行下列 T-SQL 語句,在執行時間啟用它們:

DBCC TRACEON(818, -1)

追蹤旗標 818 會啟用記憶體內部環形緩衝區,用於追蹤執行 SQL Server 的計算機所執行的最後 2,048 次成功寫入作業,不包括排序和工作檔案 I/O。 當發生 605、823 或 3448 等錯誤時,傳入緩衝區的記錄序號 (LSN) 值會與最近的寫入清單進行比較。 如果讀取作業期間擷取的 LSN 比寫入作業中使用的 LSN 還舊,則會在 SQL Server 錯誤記錄檔中記錄新的錯誤訊息。 大部分 SQL Server 寫入作業會以檢查點或延遲寫入的方式發生, (延遲寫入是使用異步 I/O) 的背景工作。 環形緩衝區的實作是輕量型的,而且對系統的效能影響微乎其微。

錯誤記錄檔中訊息的詳細數據

下列訊息不會顯示 WriteFile API 或 ReadFile API 呼叫中 SQL Server 的任何明確錯誤。 相反地,它會顯示在檢閱 LSN 時所產生的邏輯 I/O 錯誤,且其預期值不正確:

從 SQL Server 2005 開始,顯示的錯誤訊息如下:

SQL Server 偵測到邏輯一致性型 I/O 錯誤:過時讀取。 它發生在資料庫標識<DBID>碼中位於檔案 <FILE NAME>中位移<PHYSICAL OFFSET>的頁面<PAGEID>期間<Read/Write>。 SQL Server 錯誤記錄檔或系統事件記錄檔中的其他訊息可能會提供更多詳細數據。 這是嚴重的錯誤狀況,會破壞資料庫完整性,而且必須立即更正。 完成 DBCC CHECKDB) (完整資料庫一致性檢查。 此錯誤可能是由許多因素所造成。 如需詳細資訊,請參閱《SQL Server 在線叢書》。

如需錯誤 824 的詳細資訊,請 參閱 MSSQLSERVER_824

在回報此錯誤時,讀取快取包含較舊版本的頁面,或數據未正確寫入實體磁碟。 在 (寫入遺失或讀取) 過期的情況下,SQL Server 回報操作系統、驅動程式或硬體層的外部問題。

如果您嘗試復原錯誤為 605 或 823 的交易時發生錯誤 3448,SQL Server 實例會自動關閉資料庫,並嘗試開啟並復原它。 發生錯誤 605 或 823 的第一頁會被視為不正確的頁面,且執行 SQL Server 的計算機會保留頁面標識碼。 在復原期間 (讀取錯誤頁面標識符時,重做階段) 之前,有關頁首的主要詳細數據會記錄在 SQL Server 錯誤記錄檔中。 此動作很重要,因為它有助於區分遺失的寫入和過時的讀取案例。

以過時讀取和遺失寫入觀察到的行為

您可能會在過時的讀取案例中看到下列兩個常見行為:

  • 如果資料庫檔案已關閉,然後開啟,則會在復原期間傳回正確和最近寫入的數據。

  • 當您發出檢查點並執行 DBCC DROPCLEANBUFFERS 語句 (從記憶體) 中移除所有資料庫頁面,然後在資料庫上執行 DBCC CHECKDB 語句時,會傳回最近寫入的數據。

上述段落中所述的行為表示讀取快取問題,而且通常會藉由停用讀取快取來解決。 上述段落中所述的動作通常會強制快取失效,而成功的讀取會顯示實體媒體已正確更新。 遺失的寫入行為會在讀回的頁面仍是舊版數據時發生,即使在強制排清快取機制之後也一般。

有時候,問題可能不是硬體快取特有的。 這可能是篩選驅動程序的問題。 在這種情況下,請檢閱您的軟體,包括備份公用程式和防病毒軟體,然後查看篩選驅動程式是否有問題。

各種過時讀取和遺失寫入案例的描述

Microsoft 也注意到不符合錯誤 605 或 823 準則,但因為相同的過時讀取或遺失寫入活動所造成的條件。 在某些情況下,頁面會更新兩次,但具有相同的 LSN 值。 如果對象標識碼和頁面標識碼正確, (頁面已配置給物件) ,而且已變更頁面並排清至磁碟,就可能發生此行為。 下一頁擷取會傳回較舊的影像,然後進行第二次變更。 SQL Server 事務歷史記錄檔顯示頁面已以相同的 LSN 值更新兩次。 當您嘗試還原事務歷史記錄序列或數據一致性問題,例如外鍵失敗或遺失數據項時,此動作會變成問題。 下列錯誤訊息說明此條件的其中一個範例:

錯誤:3456,嚴重性:21,狀態:1 無法重做記錄 (276666:1664:19) ,針對交易標識符 (0:825853240) ,在頁面 (1:1787100) ,資料庫 'authors' (7) 。 頁面:LSN = (276658:4501:9) ,類型 = 1。 記錄:OpCode = 4,內容 2,PrevPageLSN: (275565:3959:31) .。

下列清單會更詳細地概述一些案例:

LSN SequenceAction
1   Checkpoint
2   Begin Transaction
3   Table created or truncated
4   Inserts (Pages allocated)
5   Newly allocated page written to disk by Lazy Writer
6   Select from table - Scans IAM chain, newly allocated page read back from disk (LRU | HASHED = 0x9 in getpage message), encounters Error 605 - Invalid Object ID
7   Rollback of transaction initiated
LSN SequenceAction
1   Checkpoint
2   Begin Transaction
3   Page Modification
4   Page written to disk by Lazy Writer
5   Page read in for another modification (stale image returned)
6   Page Modified for a second time but because of stale image does not see first modification 
7   Rollback - Fails - Transaction Log shows two different log records with the same PREV LSN for the page

sortSQL Server 運算子通常會在資料庫中tempdb執行 I/O 活動。 這些 I/O 作業類似於緩衝區 I/O 作業;不過,它們已設計成使用讀取重試邏輯來嘗試解決類似的問題。 本文中所述的其他診斷不適用於這些 I/O 作業。

Microsoft 已注意到下列排序讀取失敗的根本原因是讀取過期或寫入遺失:

2003-04-01 20:13:31.38 spid122 SQL Server Assertion: File: <p:\sql\ntdbms\storeng\drs\include\record.inl>, line=1447 Failed Assertion = 'm_SizeRec > 0 && m_SizeRec <= MAXDATAROW'.
2003-03-29 09:51:41.12 spid57 Sort read failure (bad page ID). pageid = (0x1:0x13e9), dbid = 2, file = e:\program files\Microsoft SQL Server\mssql\data\tempdb.mdf. Retrying.
2003-03-29 09:51:41.13 spid57 Error: 823, Severity: 24, State: 7
2003-03-29 09:51:41.13 spid57 I/O error (bad page ID) detected during read at offset 0x000000027d2000 in file 'e:\program files\Microsoft SQL Server\mssql\data\tempdb.mdf'..
* 00931097 Module(sqlservr+00531097) (utassert_fail+000002E3)
* 005B1DA8 Module(sqlservr+001B1DA8) (RecBase::Resize+00000091)
* 00407EE7 Module(sqlservr+00007EE7) (RecBase::LocateColumn+00000012)
* 00852520 Module(sqlservr+00452520) (mergerow+000000A4)
* 008522B3 Module(sqlservr+004522B3) (merge_getnext+00000285)
* 0085207D Module(sqlservr+0045207D) (mergenext+0000000D)
* 004FC5FB Module(sqlservr+000FC5FB) (getsorted+00000021)

因為過時的讀取或遺失的寫入會導致未預期的數據記憶體,所以可能會發生各種行為。 它可能會顯示為遺漏數據,但遺失數據的一些較常見效果會顯示為索引損毀,例如錯誤 644 或 625:

錯誤 644 嚴重性層級 21 消息正文在索引頁面 %S_PGID,索引標識碼 %d,資料庫 '%.*ls' 中找不到 RID '%.*hs' 的索引專案。

錯誤 625 嚴重性層級 21 訊息文字 無法從頁面 %S_PGID由 RID 擷取數據列,因為 slotid (%d) 無效。

有些客戶在執行數據列計數活動之後回報遺漏的數據列。 發生此問題的原因是寫入遺失。 也許,頁面應該連結到叢集索引頁面鏈結。 如果寫入實際遺失,數據也會遺失。

重要事項

如果您遇到任何行為,或您懷疑類似問題以及停用快取機制,Microsoft 強烈建議您取得 SQL Server 的最新更新。 Microsoft 也強烈建議您嚴格檢閱您的操作系統及其相關聯的設定。

請注意,Microsoft 已確認在罕見且繁重的 I/O 負載下,某些硬體平臺可能會傳回過時的讀取。 如果擴充診斷指出可能過期的讀取或遺失寫入條件,請連絡您的硬體廠商,立即使用 SQLIOSim 公用程式進行後續追蹤和測試。

SQL Server 需要系統支援穩定媒體的保證傳遞,如 SQL Server I/O 可靠性計劃需求中所述。 如需 SQL Server 資料庫引擎輸入和輸出需求的詳細資訊,請參閱 Microsoft SQL Server 資料庫引擎 輸入/輸出需求。