雲計算之路-阿里雲上:2013年4月7日14:15~18:35服務器故障經過


無地自容的道歉之后,向大家匯報一下故障的整個經過。在此再次向大家表示歉意,望大家能諒解!

14:15,有園友在閃存上說博客后台不能發布博文(見下圖)。

14:17左右,我們看到了這條閃存。立即進入博客后台測試,發現提交時會出現如下的錯誤:

"Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."

這是數據庫寫入超時的錯誤,對這個錯誤信息我們記憶猶新。之前遇到過兩次(3月14日4月2日),都是數據庫服務器所在的雲服務器磁盤IO問題引起的。

登上雲服務器,查看Windows性能監視器,發現日志文件所在的磁盤的IO監測數據Avg.Disk Write Queue Length平均值在5以上。性能監視器中這個值的縱坐標最高值是1,可想而知5是多么高的一個值。性能監視器中的走勢圖幾乎是一條直線。見下圖(最高值竟然達到了20,真恐怖):

 

(為什么數據庫寫入超時會表現於日志文件所在的磁盤IO高?因為數據庫恢復模式用的是Full,對數據庫的數據寫入,會先在日志中進行寫入操作。)

這次問題與3月14日磁盤IO問題的表現是一樣的,所以我們斷定這次也是同樣的原因,是雲服務器所在集群的磁盤IO負載高引起的。

14:19,我們向阿里雲提交了工單,特地在標題中加了“緊急”;

14:23,阿里雲客服回復說正在核實我們提交的問題;

14:31,阿里雲客服回復說已反饋給相關部門檢查;

14:42,沒有阿里雲客服的進一步消息,我們就回復說“如果短時間內解決不了,希望盡快進行集群遷移”(3月14日就是通過集群遷移解決這個問題的,阿里雲的技術人員也說過對於集群負載高引起的磁盤IO問題,目前唯一的解決辦法就是集群遷移);

14:47,阿里雲客服只回復說正在處理;

14:59,還是沒消息,我們心急如焚(40分鍾過去了,連個說法都沒有),在工單中說:“能不能先做集群遷移?”;

然后,接到阿里雲客服的電話,說集群中其他雲服務器占用的磁盤IO高影響了我們,他們正在處理。。。

過了會,阿里雲客服又打電話過來說可能是我們雲服務器中的系統或應用導致服務器磁盤寫入卡死,讓我們重啟一下雲服務器。(這樣的考慮可能是因為這時集群的負載已經降下來,但我們的雲服務器磁盤IO還是高。)

15:23左右,我們重啟了數據庫服務器,但問題依舊。

15:30,阿里雲客服終於決定進行集群遷移(從提交工單到決定集群遷移耗時1小10分鍾)

15:45,完成集群遷移(上次遷移5分鍾不到,這次用了15分鍾,這也是阿里雲客服所說的進行集群遷移所需的最長時間)

遷移之后,傻眼了,磁盤IO(Avg.Disk Write Queue Length)還是那么高!

為什么這次集群遷移不能像上次那樣立即解決問題?我們猜測有兩個可能的原因:

1. 遷移后所在的集群磁盤IO負載依然高;

2. 雲服務器上出現磁盤IO很高的這個分區放的都是數據庫日志文件,可能這個時間段日志寫入操作比平時頻繁(但暴增幾乎沒有可能)而且所有日志文件在同一個分區,超過了雲服務器磁盤IO的某個極限,造成磁盤IO性能驟降(可能性比較大,依據是雲計算之路-入阿里雲后:解決images.cnblogs.com響應速度慢的詭異問題)。雖然之前使用物理服務器時,日志文件也是放在同一個分區,從未出現過這個問題,但現在雲服務器的磁盤IO能力無法與物理服務器相比,而且磁盤IO會被集群上其他雲服務器爭搶(詳見雲計算之路-遷入阿里雲后:問題的根源——買到她的“人”,卻買不到她的“心”)。

不管是哪一個原因,要解決問題只有一招也是最后一招——減輕日志文件所在的磁盤分區的IO壓力。

怎么減壓呢?根據“遷入阿里雲后的一些心得”一文中的“提高整體磁盤IO性能的小偏方”,另外購買一塊磁盤空間,然后將存放博文內容的數據庫CNBlogsText(大文本數據寫入,對磁盤IO產生的壓力很大)的日志文件移至獨立的磁盤分區。

在SQL Server中,無法在線完成將數據庫日志文件從一個磁盤分區移至另一個磁盤分區。需要先detach數據庫,然后將日志文件復制至目標分區,然后再attach這個數據庫;在attach時,將日志文件的位置修改為新的路徑。

於是,在別無選擇的情況下,我們CNBlogsText數據庫進行detach操作,並且選擇了drop connections,哪知在detach的過程中悲劇發生了,detach失敗了,錯誤是:

Transaction (Process ID 124) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. 

在detach的過程中竟然發生了死鎖,然后“被犧牲”了。讓人困惑的是,不是drop connections嗎,怎么還會發生死鎖?可能drop connections是在detach操作正式開始前,在detach的過程中,還會發生數據庫寫入操作,這時的寫入操作引發了deadlock。為什么偏偏要讓detach犧牲?不合情理。

detach失敗后,CNBlogsText數據庫就處於Single User狀態。繼續detach,同樣的錯誤,同樣的“被犧牲”。

於是,重啟了一下SQL Server服務。重啟之后,CNBlogsText數據庫的狀態變為了In Recovery。

這時時間已經到了16:45。

這樣的In Recovery狀態以前沒遇到過,不知如何處理,也不敢輕舉妄動。

過了一段時間,刷新了一下SQL Server的Databases列表,CNBlogsText數據庫又顯示為之前的Single User狀態。(原來重啟SQL Server之后,會自動先進入In Recovery狀態,再進入到Single User狀態)

針對Single User狀態問題,在工單中咨詢了阿里雲客服,阿里雲客服聯系了數據庫工程師,得到的建議是進行這樣的操作:alter database $db_name SET multi_user

於是,執行了這樣的SQL:

exec sp_dboption 'CNBlogsText', N'single', N'false'

出現錯誤提示:

Database 'CNBlogsText' is already open and can only have one user at a time. 

Single User狀態依舊,出現這個錯誤可能是因為這個數據庫不斷地有寫入操作,搶占着Single User狀態下只允許唯一的數據庫連接。

(更新:后來從阿里雲DBA那學習到的解決這個問題的方法:

select spid  from sys.sysprocesses where dbid=DB_ID('dbname');
--得到當前占用數據庫的進程id
kill [spid]
go
alter login [username] disable --禁用新的訪問
go
use cnblogstext
go
alter database cnblogstext set multi_user with rollback immediate
go

當時的情形下,我們不夠冷靜,急着想完成detach操作。覺得屏蔽CNBlogsText數據庫的所有寫入操作可能需要禁止這台服務器的所有數據庫連接,這樣會影響整站的正常訪問,所以沒從這個角度下手。

這時時間已經到了17:08。

我們也准備了最最后一招,假如實在detach不了,假如日志文件也出了問題,我們可以通過數據文件恢復這個數據庫。這個場景我們遇到過,也實際成功操作過,詳見:SQL Server 2005數據庫日志文件損壞的情況下如何恢復數據庫。所需的SQL語句如下:

use master 

alter database dbname set emergency 

declare @databasename varchar(255) 

set @databasename='dbname' 

exec sp_dboption @databasename, N'single', N'true' --將目標數據庫置為單用戶狀態 

dbcc checkdb(@databasename,REPAIR_ALLOW_DATA_LOSS) 

dbcc checkdb(@databasename,REPAIR_REBUILD) 

exec sp_dboption @databasename, N'single', N'false'--將目標數據庫置為多用戶狀態 

即使最最后一招也失敗了,我們在另外一台雲服務器上有備份,在異地也有備份,都有辦法恢復,只不過需要的恢復時間更長一些。

想到這些,內心平靜了一些,認識到當前最重要的是拋開內疚、緊張、着急,冷靜面對。

我們在工單中繼續咨詢阿里雲客服,阿里雲客服聯系了數據庫工程師,讓我們加一下這位工程師的阿里旺旺。

我們的電腦上沒裝阿里旺旺,於是打算自己再試試,如果還是解決不了,再求助阿里雲的數據庫工程師。

在網上找了一個方法:SET DEADLOCK_PRIORITY NORMAL(來源),沒有效果。

時間已經到了17:38。

這時,我們冷靜地分析一下:detach時,因為死鎖“被犧牲”;從單用戶改為多用戶時,提示“Database 'CNBlogsText' is already open and can only have one user at a time.”。可能都是因為程序中不斷地對這個數據庫有寫入操作。試試修改一下程序,看看能不能屏蔽所有對這個數據庫的寫入操作,然后再將數據庫恢復為多用戶狀態。

修改好程序,18:00之后進行了更新。沒想到更新之后,將單用戶改為多用戶的SQL就能執行了:

exec sp_dboption 'CNBlogsText', N'single', N'false'

於是,Single User狀態消失,CNBlogsText數據庫恢復了正常狀態,然后嘗試detach,一次成功。

接着將日志文件復制到新購的磁盤分區中,以新的日志路徑attach數據庫。attach成功之后,CNBlogsText數據庫恢復正常,博客后台可以正常發布博文,CNBlogsText數據庫日志文件所在分區的磁盤IO(單獨的磁盤分區)也正常。問題就這么解決了。

當全部恢復正常,如釋重負的時候,時間已經到了18:35。

馬后炮 

如果我們提交工單后,阿里雲客服決定進行集群遷移不是1小時10分鍾,而是10分鍾后,故障時間就可以縮短1小時。

如果我們先想辦法屏蔽對CNBlogsText數據庫的所有寫入操作,然后再detach,故障時間又可以縮短至少1小時。

可是這兩個如果都沒發生,結果代價慘重,讓故障在訪問高峰期持續了4小多小時,給成千上萬的園友造成了麻煩,真是罪孽深重,無地自容。。。

亡羊補牢

舍雲服務器,取RDS。

之前舍RDS取雲服務,原以為可以用更多的內存彌補雲服務器磁盤IO性能低的不足。但萬萬沒想到,雲服務器的硬傷不是在磁盤IO性能低,而是在磁盤IO不穩定。

阿里雲對我們這次遇到的故障很重視,會幫助我們將數據庫服務器從雲服務器遷移至RDS。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM