共用方式為


SQL Server 診斷會偵測因讀取過時或寫入遺失而未報告的 I/O 問題

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

原始產品版本:SQL Server
原始 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 錯誤:讀取過時。 在檔案 <FILE NAME>中位移<PHYSICAL OFFSET>的資料庫標識碼<DBID>頁面<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。 Log: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

SQL Server sort 運算子通常會在 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 訊息文字無法從 RID 頁面 %S_PGID擷取數據列,因為 slotid (%d) 無效。

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

重要

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

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

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