南京市口腔醫院 江蘇 南京 210018
鑒于我院的數據庫在2020年4月12日及4月13日兩天接連鎖表,且鎖表時間段均為非業務高峰期。我們對數據庫環境進行了為期一個月的監控以及相關優化。
眾所周知,數據庫健康狀態最為明顯的體現就在于I/O讀寫的速度快慢,索引所使用的磁盤空間越大則sql語句運行的就更為緩慢,當運行緩慢的sql產生了阻塞及互相等待的時候就會造成數據庫的鎖表現象,鎖表主要分為以下類型:
(1)共享鎖。S鎖,也叫讀鎖,用于所有的只讀數據操作。共享鎖是非獨占的,允許多個并發事務讀取其鎖定的資源[1]。
(2)排他鎖。X鎖,也叫寫鎖,表示對數據進行寫操作。如果一個事務對對象加了排他鎖,其他事務就不能再給它加任何鎖了。
(3)更新鎖。U鎖,在修改操作的初始化階段用來鎖定可能要被修改的資源,這樣可以避免使用共享鎖造成的死鎖現象。
鎖表當日對數據庫情況進行分析,優先排除了HIS數據庫服務器壓力過大原因導致的鎖表。同時分析,HIS數據庫在相當長的一段時間內并未發生鎖表問題,懷疑是由于業務科室偶發性的跨大時間段的數據查詢,引起數據庫超負荷,導致數據庫鎖表。問題發生時的緊急處理方式是殺掉引起鎖表進程。除此之外并沒有更好的方式。為了預防和解決此類現象我們對該數據庫進行了分析和處理[2]。
通過實時數據查找,發現mz_visit_tale,mz_detail_charge,gh_detail_charge等業務主表的數據量過大,最大數據量達到3000w。已經對相關臨床科室的使用造成影響,我們進行了即時處理,并通過后臺進行數據遷移,將一周前的數據遷移至相應的B表中保存。
在進行完第一階段的處理過后,對數據庫I/O讀寫情況進行監控,分析4月24日高峰期數據結構,當日的I/O讀寫在3-4w,5-6w,10-20w,100w+的數據量過高,優先處理可能會導致鎖表的I/O較高的語句,優化方式如下:建立C表,將B表的數據定期轉移至C表中保存,保證數據不丟失。但是此操作有可能導致各個職能科室的數據調取出現問題。針對此問題我們建立了備份庫進行跨月跨年的大數據查詢。防止在業務高峰期進行的查詢與醫院日常業務撞車導致的鎖表問題。對整個數據庫的業務主表進行索引重構,降低掃描開銷,增加掃描
在第一階段處理完成之后我們在4月29日對數據庫進行同期I/O檢測,分析可以看出5-6w,10-20w的語句數量依舊較大,分析有關語句并對其進行優化,優化策略如下:對自助機,院長報表查詢中的語句使用大數據量視圖修改為小數據量的業務表,減少每次抓取的數據范圍。對自助機,各種APP的掛號,取號的相關存儲過程進行修改,充分利用現有表結構中的索引以及主鍵,減少表掃描和鍵值查詢所用的I/O開銷[3]。
在第二次優化處理之后,又對4月30日的數據庫情況進行跟蹤并分析,可以得出5-6w的數據量依舊沒有優化,又對這個區間的sql語句進行相關的分析,做出如下策略:檢查相關的表結構做優化,對相關表建立如下非聚集索引以減少表掃描的相關I/O開銷。
在上次優化之后,又對數據庫健康狀態進行持續的跟蹤,并在5月18日發現了相關的數據庫異常狀態得出,3-4w,10-20w的數據量異常較多,對相關語句進行分析后發現問題主要出現在微信掛號,以及起航相關數據抓取的語句上,做出相關修改。首先對表jd_yyhh建立相關非聚集索引,以減少APP掛號取號的相關表掃描開銷。并為修改相關接口增加update時的運行效率,其次優化APP取號的存儲過程,將表gh_receipt中的索引條件利用起來。經過一系列的優化操作之后,南京市口腔醫院的數據庫健康狀態已經達標。此后一直又對數據庫健康狀態進行持續的跟蹤,至今關于我院的數據優化工作已經取得了實質性的進展[4]。
此次數據庫鎖表事件主要原因在于忽略了對數據庫健康情況的檢測,此次事件無疑為我們敲響了警鐘。此后在日常維護的過程中一定要做到經常查看,出現問題及時響應。在進行sql語句編寫的時候一定要進行語句分析,開銷計劃分析,對錯爛語句要及時發現及時處理,減少對于數據庫造成的影響。對數據庫數據的數量級要進行及時監測,防止業務表的數據過大導致的表鎖或者運行緩慢。