唐顯歲



關鍵詞:HIS系統;SQL Server數據庫;死鎖;數據庫運維
0 引言
SQL Server是由微軟公司開發的一個大型的關系型數據系統,它為用戶提供了一個安全、可靠、易管理和高端的客戶/服務器數據庫平臺。隨著現代數據庫應用業務范圍的拓展,用戶對數據庫性能的要求,運維人員對數據庫管理的要求都在不斷提高,而SQLServer就是這樣一種高性能的關系型數據庫,它以客戶端/服務端為設計結構,支持多個不同的開發平臺,支持企業級的應用程序,支持XML等,能夠滿足多種類型的數據庫應用場景[1]。因此,SQL Server數據庫被廣泛地應用在醫療、教育、商場等各行各業中,它為使用者提供了一個全面的數據管理和業務智能平臺。但是,在實際應用場景中,面對繁忙的業務、復雜的場景以及海量的數據,難免會出現不同的故障需要調試,數據庫死鎖就是其中之一。
SQL Server數據庫貫穿HIS系統設計、開發、實施和運行的全過程,HIS系統具有流程復雜,數據量龐大的特點,醫院業務要求其具有相應速度快且可靠性高,在實際應用中,死鎖會使數據服務的終端無法進行任務操作,并帶來極大的危害且可能導致整個HIS系統癱瘓[2]。
本文通過作者在日常維護中遇到的數據庫死鎖問題進行分析,并將處理方法進行梳理,以方便為數據庫運維人員在處理此類問題時提供一些思路及方法。
1 SQL Server 數據庫鎖管理機制
1.1 鎖模式
在SQL Server數據庫中針對不同的資源,存在不同的加鎖方式,即鎖存在多種模式[3],具體包括共享鎖、更新鎖、排它鎖、結構鎖、意向鎖、批量修改鎖,詳細用途如表1所示。
1.2 鎖粒度
根據SQL Server數據庫中用戶可以操作的數據行、索引以及數據表的不同,鎖有多粒度的概念,即可以鎖定資源的層次[4],資源粒度包括:數據庫、表、區域、頁面、鍵值、行標識符。多粒度鎖用于保證數據的完整性和支持并發操作,收到用戶SQL請求,自動分析并在數據庫中加上相應的鎖[5]。
1.3 死鎖概述
SQL Server數據庫系統中,當多個事務分別鎖定了某種資源時,又發出請求試圖鎖定其他事務已占用的資源,每個事務都在等待另一個事務釋放鎖,結果造成任務一個事務都無法繼續執行,從而形成了請求鎖的循環,產生死鎖,即產生永久阻塞的特殊場景[6]。圖1為兩個事務產生死鎖的例子。
此時我們有兩個線程,分別是線程A和線程B,假設線程A現在持有了鎖A,線程B持有了鎖B,然后線程A嘗試去獲取鎖B,當然它獲取不到,因為線程B還沒有釋放鎖B。然后線程B又來嘗試獲取鎖A,同樣線程B也獲取不到鎖A,因為鎖A已經被線程A持有了。這樣一來,線程A和線程B就發生了死鎖,因為它們都相互持有對方想要的資源,卻又不釋放自己手中的資源,形成相互等待,而且會一直等待下去[7]。
2 問題描述與分析
某三甲醫院于上午九時左右多個臨床科室報應用程序故障,HIS系統使用非常卡慢,部分科室甚至出現無法進行任何操作的情況,此時正值臨床業務繁忙時段。接臨床科室故障報修后,運維工程師根據故障信息的描述以及故障影響的范圍,迅速就反饋的問題分析有可能造成此類問題的原因:
2.1 服務器集群出現故障
服務器集群即多個服務器一起工作,可以減少單點故障的數量[8]。可能會出現主機不能加電,自檢報錯、自檢過程中所顯示的配置與實際不符等多種故障。
2.2 內部網絡出現故障
內部網絡即醫院內部的專用網絡,以Web為核心應用,構成統一便利的信息交互平臺[9]。可能會出現整個局域網都不能上因特網、網絡適配器與計算機資源沖突和網速過慢等故障。
2.3 客戶端/服務端資源空間不足
隨著業務流量的劇增,客戶端/服務端可能運行程序過多、應用程序沒有及時釋放內存、受到網絡攻擊等問題,導致服務器資源被大量占用,出現空間不足的情況。
2.4 SQL Server 數據庫服務運行異常
常見的SQL Server數據庫服務運行異常包括數據庫服務未啟動或直接報數據庫服務異常,一般原因為數據庫程序損壞或是軟件安裝的數據庫服務未啟動[10]。
2.5 SQL Server 數據庫出現死鎖情況
因爭奪資源而造成一種互相等待的情況即死鎖,可能會出現事務之間對資源訪問順序的交替、并發修改同一記錄和索引不當導致死鎖的情況。
3 問題處理
在本節中,我們將之前分析的故障情況具體去操作驗證,以便排查出故障的根本原因并予以處理。
3.1 查看服務器集群運行狀態
服務器集群管理的目的就是提高服務器性能,同時在出現故障時能及時進行故障轉移,提高服務器的可用性,保障應用業務的穩定性。登錄服務器集群管理平臺,查看服務器運行狀態是否正常,查看服務器日志有無異常記錄。
3.2 檢查內部網絡運行情況
根據醫院內網網絡拓撲圖,依次檢查網絡核心層、匯聚層及接入層的交換機運行狀態是否正常,查看日志記錄是否正常。特別是對于故障報修的臨床科室,檢查此區域內局部網絡是否暢通,終端設備是否能夠正常連接。
3.3 檢查客戶端/服務端資源空間
檢查客戶端終端設備資源空間使用情況,排查是否出現磁盤空間不足或內存被惡意侵占等情況;打開數據庫服務器,檢查服務器資源空間使用情況是否正常,如果資源不足,可通過適當擴容來解決問題。
3.4 檢查SQL Server 數據庫服務運行
打開SQL Server配置管理器,檢查SQL Server服務狀態是否運行正常。如果運行異常或未運行,可嘗試重啟下服務,并查看下服務日志,進一步排查原因,確保SQL Server數據庫服務運行正常。
3.5 查看SQL Server 數據庫應用情況
打開SQL Server數據庫管理工具,通過使用sys.dm_tran_locks動態管理視圖查看活動鎖的信息,也可以使用sp_lock存儲過程來查看,當發現死鎖后,應排查引起死鎖的原因和影響的范圍,可選擇使用KILL命令結束產生死鎖的進程ID,釋放資源,確保數據庫的運行正常。圖2為作者在數據庫運維過程中創建的查看數據庫死鎖的存儲過程,它能夠非常便捷直觀地顯示死鎖的詳細信息,可供參考。
通過上述問題分析和問題排查,引起此次HIS系統卡慢的情況是由于新上線的一個小模塊中某個視圖產生大量的查詢語句,剛好與醫院業務數據操作繁忙時段相沖突,因此引起數據庫死鎖現象,造成應用程序卡慢,系統無法操作等故障。最后,通過清理死鎖,釋放資源,同時優化視圖,使得數據庫運行正常,HIS系統恢復正常。
4 預防和避免死鎖及優化效果
4.1 預防和避免死鎖
鎖在數據庫中是一個非常重要的概念,它可以防止事務的并發問題,在多個事務訪問下能夠保證數據庫的完整性和一致性。本案例中,造成HIS系統卡慢的根本原因就是數據庫死鎖,那么在日常使用中該如何預防和避免死鎖呢?
數據庫設計的優劣直接影響到系統的運行效率,為了避免死鎖我們遵循以下原則,首先是通過增加數據冗余和數據劃分兩種途徑非規范化設計數據庫;其次在頻繁更新的列上、搜索參數上建立合適的索引;最后對頻繁訪問的表,應適當減少頁分裂次數[11]。
同時可以依據數據庫關于鎖的機制、鎖模式以及鎖的粒度管理來有效的預防和避免死鎖的產生[12]。通過適時地對數據庫表結構、索引建立等進行調優,提高數據庫的使用性能;優化存儲過程、視圖等SQL語句,避免頻繁地在其內進行增刪改查操作,占用過多的資源;較大數據量的查詢避開臨床業務使用的高峰期,降低資源搶占的現象;合理地對數據庫服務器進行資源的調整,加大數據庫服務器的容量提升性能等都能夠有效的預防和避免數據庫死鎖的產生。
4.2 優化效果
經過對SQL Server數據庫的上述優化處理,清理了系統中大量的垃圾,合理地規劃了數據庫,極大地提升了處理速度。經過系統真實的醫療數據運轉環境下的業務測試,及時地預防了死鎖的發生;重視數據的分布和流動性,數據量的增大及數據模型的改變均不會影響到系統的響應速度。
5 結束語
數據庫的死鎖問題是數據庫日常維護工作中的常見問題,我們應當充分認識和了解數據庫中關于鎖的相關機制,如鎖模式、鎖粒度及死鎖,并盡量做到預防和避免死鎖的產生,這樣既能保證數據庫系統安全穩定地運行,又能為實際應用工作者節約寶貴的時間,避免了日常軟件運行過程中出現停頓鎖表的現象,同時還能提高運維人員的工作效率,從而為患者提供流暢、高效、便捷的醫療服務。