標籤:style blog http color 檔案 資料
最近有客戶反映,機房出現斷電情況,伺服器的系統重新啟動後,資料庫服務自啟動失敗。第一次遇到這種情況,為了查看是不是斷電情況導致資料庫檔案損壞,從客戶的伺服器拿到資料庫的日誌,進行分析。
資料庫工作機制
要分析資料庫啟動失敗的原因,首先說明一下資料庫服務的工作機制。
資料庫分為六大服務:
資料庫的六大服務之間存在依賴關係,及啟動流程:
服務自動啟動失敗原因
從客戶那裡,拿到了兩份日誌,一份是開機自啟動的日誌資訊,此次資料庫啟動失敗。另外一份是開機後,手動啟動資料庫服務的日誌資訊,此次資料庫啟動成功。
首先看第一份日誌:
從日誌中看到,快照資料服務已經成功啟動,但是沒有後續的日誌資訊,說明問題可能出在snapshot服務,或者下一個將要啟動的equation服務。而另外一份日誌中看到所有的服務都成功啟動,並且正常運行,這就排除了伺服器意外斷電導致檔案損壞的可能。
資料庫可以通過手動的方式成功啟動,說明資料庫的檔案資訊都正確,但是第一啟動時卻只logger、historian、snapshot服務成功啟動,由於後續沒有日誌輸出,很難分析問題的原因。
既然資料庫沒有相應的日誌,那麼就要通過系統日誌來分析,此處需要尋求系統的事件記錄的協助。
在電腦管理中找到事件檢視器,選擇系統,如:
預設情況下,服務出現啟動失敗等異常時,作業系統會記錄一些系統事件。
從中可以看到如下資訊:
snapshot 服務啟動時掛起事件ID 7022
有事件ID與事件描述,Google之,但是沒有找到相應的解決方案,沒辦法,還是只能從資料庫日誌來分析。
再次分析日誌,看到這樣一種情況:
snapshot服務從開始啟動,到啟動結束,共耗時兩分半,這個時間對於Windows服務的啟動來說,時間是很長了。根據此情況,以及系統事件的描述,推測,有可能是服務啟動逾時。
為了驗證此推測,在資料庫服務啟動時加入一個Sleep(60000),這個時間足夠逾時了。從服務管理員中啟動服務,過了一段時間後,服務啟動失敗,從事件檢視器中,看到”服務啟動時掛起的訊息”,由此基本上可以斷定資料庫服務是由於逾時而啟動失敗的。
服務啟動逾時原因
知道服務啟動失敗原因是逾時導致的,還需要分析一下為什麼開機自啟動的時候服務會啟動逾時。
還是從日誌開始,幸好日誌中有詳細的輸出日誌,從這些日誌中,看到兩個耗時比較長的操作:
鎖定曆史資料緩衝與鎖定曆史資料補寫緩衝兩個操作,耗時分別在一分鐘左右,兩個操作一起佔了啟動耗時的大部分時間,那麼啟動逾時就是由這兩個操作導致的。
既然這兩個操作比較耗時,那麼他們在悄悄的做什麼呢。這兩個操作實際是在鎖定實體記憶體,使其盡量不要交換到磁碟上,那麼開機啟動後,所有的快取資料還沒有載入到記憶體中,此時鎖定此記憶體,就會導致作業系統將此快取資料從磁碟載入到記憶體中。看似複雜,實際就是作業系統在讀磁碟,而機械磁碟的讀取速度是有限並且非常慢的,當快取檔案很大時,純粹讀取磁碟的時間就要很長。而此案例中,兩個快取檔案都在15G左右,所以耗時也就比較長了。
由此分析下來,也就找到了服務啟動逾時的原因了。
服務第二次啟動時順利啟動的原因分析
這還沒完,服務啟動逾時的原因是知道了,但是為什麼第二次啟動時,就可以順利啟動呢。接著分析。
再來看第二次啟動時的日誌:
此日誌中看到,第一次啟動中,每個佔用耗時達到60秒的鎖定記憶體操作,此次只有3秒,可以說非常迅速了。
上面說到,鎖定記憶體實際是在讀取磁碟,而磁碟速度特別慢,15G的快取檔案,在3秒內讀取完,是根本不可能的。那麼唯一的可能就是根本沒有讀取磁碟。
其實這是Windows的一個記憶體管理機制,記憶體對應檔在卸載的時候,並不會立即去釋放記憶體,釋放記憶體的時機是由作業系統來決定的。當snapshot服務在很短的時間內又重新載入此記憶體對應檔時,作業系統發現此記憶體對應檔還存放在記憶體中,那麼就不會再載入了,因為讀取磁碟的速度實在是太慢了。而在開機啟動的時候,由於是第一次載入記憶體對應檔,記憶體中還不存在,就會讀取一次磁碟。所以這個鎖定記憶體的時間也就由第一啟動時的60秒變為3秒了。
設定Windows服務啟動逾時時間
Windows系統的服務逾時時間預設是30s,當一個服務的啟動時間超過這個時間後,服務管理員會認為服務存在異常,並視為啟動失敗,然後記錄一些系統事件資訊。但是有時候這個時間是比較短的,比如我們的snapshot服務,這就需要修改註冊表來解決這個問題。登錄機碼為HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/ServicesPipeTimeout,這個值有可能不存在,如果不存在需要添加。類型為DWORD,單位是毫秒。
當然,這個逾時時間是對所有服務都有效,修改這個值並不是最好的解決辦法。最好能在snapshot程式內部,對啟動時載入緩衝流程進行最佳化,以縮短啟動時間,或者將耗時比較長的操作放到啟動後進行。
總結
- 可以通過修改註冊表來修改Windows的服務啟動逾時時間。
- Windows的一個記憶體管理機制,記憶體對應檔在卸載的時候,並不會立即去釋放記憶體,釋放記憶體的時機是由作業系統來決定的。當程式在很短的時間內又重新載入此記憶體對應檔時,作業系統發現此記憶體對應檔還存放在記憶體中,那麼就不會再載入了。
當然,還有最重要的一點,日誌系統很重要,騷年,乖乖的給程式加日誌去吧!
系列連結
玩轉Windows服務系列——建立Windows服務
玩轉Windows服務系列——Debug、Release版本的註冊和卸載,及其原理
玩轉Windows服務系列——無COM介面Windows服務啟動失敗原因及解決方案
玩轉Windows服務系列——服務運行、停止流程淺析
玩轉Windows服務系列——Windows服務小技巧
玩轉Windows服務系列——命令列管理Windows服務
玩轉Windows服務系列——Windows服務啟動逾時時間