- 工信部備案號 滇ICP備05000110號-1
- 滇公安備案 滇53010302000111
- 增值電信業務經營許可證 B1.B2-20181647、滇B1.B2-20190004
- 云南互聯網協會理事單位
- 安全聯盟認證網站身份V標記
- 域名注冊服務機構許可:滇D3-20230001
- 代理域名注冊服務機構:新網數碼
在經歷了上面的文件級別錯誤后,在數據庫啟動的過程,還經常出現的是數據頁級別的錯誤,相對于上面的文件錯誤級別,在數據頁中造成的錯誤粒度更小,并且基本不會反映到數據庫級別,也就是說在出現數據頁級別的錯誤時候,該數據時可以正常訪問的,只是在訪問有錯誤的數據頁的時候才會報錯,在我們遇到這種錯誤的時候該如何解決呢?
下面我們依次來分析,首先我們來制作一個經典的824錯誤,以下部分內容牽扯到數據庫部分基礎,限于篇幅,我們不做詳細介紹:
<1>首先我們在我們的測試庫中新建一個表,我們將該表新建成一行為一個數據頁的方式,也就是說一行數據庫在數據庫中就能承載一個數據頁
USE CnblogsTestDB GO CREATE TABLE [dbo].[TestPage] ( [a] [int] NULL, [b] [nvarchar](3900) NULL ) ON [PRIMARY]
腳本很簡單,一張表,兩列,一列int類型,一列nvarchar(3900),一行數據的存儲空間為:3900*2(nvarchar(3900))字節+4(int)+96字節(頁頭)+36字節(行偏移)=7932字節,我們知道一個數據頁存儲的信息為8K=8192字節,包括其它消耗所以該表一行數據如果填充完,一行數據將近乎占據一個數據頁。
我們來添加三行數據,然后查看頁信息:
--插入三條數據 insert [TestPage] values(1,REPLICATE('A',3900)) insert [TestPage] values(2,REPLICATE('B',3900)) insert [TestPage] values(3,REPLICATE('C',3900)) go--查看頁信息 dbcc traceon(3604)--查看庫中頁集合 dbcc extentinfo(CnblogsTestDB,[TestPage])
可以看到,該表中現在有三個數據頁,我們來看看數據頁應該也是近乎沾滿的
上圖顯示了,通過掃描表信息,共含有3個數據頁,每個數據頁中的數據量存儲占比到了96.55%,也就是說基本上是填充滿了。
當然,我們還可以通過DBCC PAGE命令,來查看每個頁中的具體內容,我們簡單的看一個頁面編號為90的數據頁:
通過上面的命令可以看到,該數據頁中存儲的為表中的第一行的數據,并且在數據庫存儲文件中是以十六進制方式編碼存儲。
當然,如果感覺此方式不直觀,可以利用一個小工具進行數據頁的查看,這里我推薦使?Internal Views(此工具在樺仔的博文中有詳細介紹),可更直觀的展示數據存儲頁信息:
這里我們可以點擊我上面上面查看的第一行的數據內容頁進行查看
經過上面的分析步驟,其實我的目的是想重現在SQL Server啟動過程中,或者在線上的數據庫經常遇到的經典錯誤824錯誤
上述過程是原理篇,因為我們必須知道數據存儲的底層原理,才能理解好這個錯誤的原因,以及找到正確的處理方法。
下一步,我們來重現這個錯誤的原因,我們知道在我新建的測試表中含有兩個字段:a和b,并且a為int類型、b為nvarchar類型
然后我們介紹了底層的存儲機制,我現在將第一列a字段的整形數據內容存儲改成字符串類型,依次來損壞掉該數據頁內容
我先將服務停掉,然后用文件編輯工具,修改此數據頁內容,該數據頁內容為十六進制內容,當然在我搞壞這部分數據頁之前我先做一個完整備份
然后修改該數據頁信息,這里我使用UltraEdit文本編輯工具,打開文件,找到該數據頁內容
我們將上面的源數據更該一下,來把這個數據頁損壞掉
我們保存,然后重新啟動該數據庫看看
這就是我們平常比較常見的824錯誤的過程,而此過程有可能是磁盤壞道造成,或者誤修改文件等諸多原因,但是此問題還是比較常見的
當然,這種數據頁面的損壞可能造成的影響不是庫級別的,也就說不會造成數據庫不能訪問,其它表是能正常訪問的,但是只是在操作此損壞的數據頁的時候才會報錯,但有時候這幾個數據頁的損壞對業務產生的影響有可能就是致命的,所以我們要解決掉。
鄭重提示:上面過程也可以正確的更改數據頁中的數據,但是如果沒有確切的把握,基本上能把數據庫搞癱瘓掉,我是為了重現問題才修改底層元數據,所以在自己的生產庫中千萬不要亂搞!
在數據庫啟動的過程中,會發生一致性校驗,所以該錯誤應該會記錄到Error的錯誤日志文件中,我們來看:
windows平臺下的錯誤日志:
當然,在啟動的過程中該問題有可能發生很多,比如磁盤壞道等原因,一系列的數據頁可能就沒法訪問了。所以SQL Server會將這些損壞的頁面記錄到msdb系統庫中,這我們在這個庫中查找到損壞的頁面集合:
至此,我們已經重現了經典的824錯誤,那我們該如何解決此問題呢?
解決方法:
a、如果此問題出現的頁面為數據承載頁,也就說該頁存儲的為內容數據或者為聚集索引的葉子節點數據,并且存在鏡像,版本在SQL Server2005以上,那么這個錯誤基本可以忽略,SQL Server能夠自動幫你修復此錯誤。
b、如果此問題出現在沒有鏡像的環境中,那就要區分是損壞頁面是否為聚集索引葉子節點數據,如果是,那就簡單了,直接重建索引就好了,如果不是,那此種方案還是不能解?,判斷方法如下:
利用DBCC PAGE命令查看當前數據頁內容,根據ObjectId跟蹤該頁位于哪個對象上,Metdata:IndexID的值判斷是否為索引樹中的節點值,如果大于0則表示為索引值,此時,重建該索引既可以。比如:
我們根據該頁的ObjectID,從數據庫中查找該頁所屬對象。
c、如果上述方案都不能滿足,那只有采取此種方案,我們可以利用數據庫備份進行還原,當然為了最大限度的避免數據庫離線,我們最好采取數據頁還原的方式,此種方式最為簡單,還原速度也最快,能夠最大限度的縮短數據庫離線時間,并且保證數據完整性。
這里提示下:在SQL Server2012版本一下,SSMS不提供圖像化數據頁還原方式,在SQL Sever以后的版本中,有圖像化界面操作。
所以,我們只能通過如下腳本進行還原:
RESTORE DATABASE CnblogsTestDB PAGE='1:90'FROM DISK = N'F:SQLTestCnlogsTestDB.bak'WITH NORECOVERY
當然有事務日志、更新備份的,需要依次恢復這過程的所有的備份,不要忘記備份尾部日志。
但是此方法也有局限性:
如果損壞的數據頁為
1、分配頁:GAM、SGAM和PFS頁
2、所有數據文件的啟動頁
如果發生損壞的是以上兩種,則無法通過該備份恢復頁方式進行恢復。如果這種情況下,建議考慮找合適的時間段進行全庫的恢復操作。(推薦)
d、上述情況是在存在有備份的情況下,如果沒有數據庫備份,那我們只能選擇最后的一招了,那就是DBCC CHECKDB命令,同樣和上面一樣,此種方式可能會造成數據丟失,所以不建議采用,如果能容忍數據丟失,采用的過程參照文中的上半部分。(不推薦)
至此,我們已經完成了一個SQL Server啟動過程或者平常最經常遇到的一個經典錯誤824錯誤,我們來總結下:
824錯誤原因:大部分是由于磁盤存儲導致的數據頁損壞,導致的SQL Server在讀取的時候發生了錯誤。
導致錯誤場景:磁盤壞道、突然斷電等情況下經常會出現此錯誤。
----------------------------------------------------------霸氣的分割線-----------------------------------------------------------------------
和824錯誤相關的還有一種是823錯誤,我們來介紹下該錯誤信息
由于場景所限,我就不重現該錯誤了,在這里我詳細的介紹下這兩種錯誤的原因和原理,就可以了,如果遇到了,解決的方式基本都是一致的,可參照上面的824錯誤解決方法。
SQL Server在每次寫入頁面的時候,會根據頁面里的數據算出一個校驗值?一同存儲到頁面中去。當下次讀取頁面的時候,再根據這次讀到的頁面數據,算出一個新的校驗值。如果寫入和讀出的數據一模一樣,那么兩個校驗值就是相等的。如果兩個校驗值不相等,就意味著上次SQL Server寫入的數據和這次讀取出來的一定不同,現在讀取出來的數據就有問題了。
823錯誤就代表著SQL Server在向操作系統申請某個頁面讀寫的時候遇到了Windows?取或寫入請求失敗。所以該問題的原因大部分是源自于操作系統層面,更確切的說是物理文件損壞而導致此錯誤,比如設備驅動程序導致等。
824錯誤則是在讀取數據頁面時候,發現數據頁面有問題,比如讀取出來的校驗值不對等。
當上面描述的823和824錯誤出現大面積的時候,或者直接部分數據文件完全壞掉的情況下,在SQL Server啟動過程中就會出現數據庫SUSPECT“質疑”狀態。
經過我的多次數據頁的破壞和摧殘,我已經順利的將我們的這個測試庫給搞成?質疑狀態,我們來看SUSPECT(質疑)的狀態庫:
這里我直接DBCC CHECKDB命令嘗試著恢復下看看
所以到此,我們要做的就是避免上述錯誤的發生。如果在生產庫中?生了我上面的情況,然后沒有數據庫備份,那么剩下來你要做的事情:我估計就是準備簡歷了.....
結語
文章主要還是分析SQL Server啟動過程中,加載用戶數據庫的時候,所遇到的一系列問題,文中部分內容需要有一定數據庫基礎知識才能讀懂,篇幅有限,我們沒有做深入的講解分析,比如上面的幾個重要的命令DBCC PAGE....DBCC CHECKDB..等等,隨便一個都能寫出一系列的內容,我們側重的還是問題的解決,和問題原因分析,后續文章中會介紹這一系列的命令作用,以及正確的使用技巧。
文中部分數據庫錯誤都是我耗費精力一步一步調整出來,目的是真實的展現錯誤明細,其實問題解決容易,問題重現的過程復雜。
如果經常使用SQL Server,其實這些問題都是我們會經常遇到的,所以我們要記住相應的解決方案,做的有備無患!
售前咨詢
售后咨詢
備案咨詢
二維碼
TOP