《全程回放:100T核心數據庫升級歷險記》要點:
本文介紹了全程回放:100T核心數據庫升級歷險記,希望對您有用。如果有疑問,可以聯系我們。
講師介紹
汪洋,從事Oracle相關開發運維工作20年.現任平安科技數據庫技術部總監,負責數據庫技術引入,數據庫產品選型、架構設計、規范制定,開發、測試、生產環境運維等工作.近年,對開源數據庫技術以及DBaaS產生濃厚興趣,一直致力于相關的研究和引入工作.
本次分享大綱:
正如前面提到的,它是全球最大的Oracle 9i OLTP數據庫,甚至連原廠的工程師都不敢碰它,覺得這個任務似乎不可能完成.剛剛也說了,五年前我們曾經失敗過一次,那時它才只有10個TB,五年之后,業務數據量變成了110個TB,現在每個月仍在以3TB的速度往上增長,而且是9i版本.眾所周知,9i是個非常老的產品,它可能在設計的時候就沒想過去運行這么大的一個在線數據庫.
我們看到,它的業務數據量有110TB+,每秒的事務量是2000+,大家可能覺得這事務量不是很高,因為現在都是一萬或十幾萬事務量,但我想告訴大家的是,保險不同于其他行業,它的每個事務都需要涉及到非常復雜的計算后才能提交,所以不同系統的TPS事務量代表的意義是不一樣的.對于產險數據庫來說,它已有的數據量已經是非常高的了,五年前只是現在的1/7,五年后翻了7倍.此外,它每天處理的SQL量有50多萬,基本上支撐著平安產險95%以上的業務.如果萬一發生問題,造成的影響與損失可想而知.
首先,Oracle 9i版本的延展服務在2011年的7月已經到期了,所以出了問題會怎樣?如果大家用Oracle的話,出了問題,還是可以通過請求GCS (Oracle 全球技術支持)來幫你解決,但如果是新Bug的話,它是不會讓O染成了研發介入開發新patch的,它只能有一些Workaround去幫你規避.如果連Workaround都沒有,那你就只能像踩著鋼絲一樣,天天擔心自己會不會遇到這些新的Bug.假如真的遇到了,也得自己想辦法如何去規避.其實運行這么多年,我們也通過一些已知的辦法去規避,但這始終不是長久之計.基于這些原因,必須要去升級.
第二個是硬件擴展的瓶頸.它不光是數據庫本身廠商的不支持, 更是強調一個生產圈的不支持,包括它的主機、操作系統都不再服務支持.如現在我們這個新購的主機上只能運行Solaris 11,而Solaris 11 又只認證Oralce 11g以后版本的數據庫,所以不及時升級的話,新采購回來的硬件只能認證比它高的版本,你仍繼續用9i,發生問題時,廠商是沒有辦法解決的,甚至你要冒風險去運行在一個不被認證的操作系統上.還有就是剛才提到的硬件的存儲,我們的數據庫有110TB,而數據量每個月仍在以3T的速度往上增長,而舊的整個存儲最大的容量也就130TB,很快就會達到它的瓶頸.
我們在2013-2014年出現了三次UIOC(ugency incident office center),相當于一個作戰史,一共發生了三次,而且每次都與latch: cache buffers chains等待事件相關.其實在9i里面我們感覺已經沒有一個很有效的辦法可以解決這個問題了,而在更早之前,從2009-2014年間更出現了12次重大事件,其中5次與執行計劃突變有關,這些都是我們用9i時遇到過的問題,急需把它升級為11g.
維護9i所投入的人力成本是非常大的.為什么這么說呢?因為9i是一個比較舊的技術,很多時候我們的解決手段都必須在更高的版本上去實現,而在9i上做一個技術的變更非常復雜,你要考慮得非常細致,很多變更不能通過在線操作.如果升級到11g,不光可以釋放一部分的人力,還能把這部分的人力投入到更有價值的事情上去.
我們平時數據庫升級一般遵循的都是一次只做一個變更,但這次情況不同,就像前面提到的受限于硬件、存儲等多個瓶頸,我們一次做了四個變動,這也是為什么這次升級如此復雜的原因之一.其中,操作系統是從Solaris 10升級到了Solaris 11,DB版本從9.2.0.5升級到了11.2.0.4,主機硬件從M9000升級到T5-4,存儲硬件是從高端SAN變更成了閃存.現在閃存是未來存儲的趨勢.
以上這些都是我們在做方案時提出的挑戰和要求.
如果一開始的選擇就是錯的,即使后面你do things right,最后的結果也不一定是對的.因此在升級之前,我們要做出正確的選擇.
這是方案大致的流程.首先要走基礎的硬件上架和基準的測試,比如說,存儲的IO能力能不能達到我的要求,雖然理論上閃存是要比以前高端SAN要強很多,但沒有經過實際測試過,也是無法確定的,所以需要自己做一遍測試.主機呢,我們也是把真正的生產系統切換到新的主機上進行試運行一次,看T5-4到底是不是要比M9000要好,避免發生我們預期不到的事情.經過這樣一輪測試,我們才有信心、鄭重地做硬件架構升級后的生產運行平臺.接下來,一方面是做性能測試,一方面是要做功能方面的回歸測試,最后還要聯調再做一次終極的性能驗證.做完之后,用戶接受、開發接受,然后再做系統真實的投產上線和運行.
首先我們碰到的第一個難題就是DB Replay,用過Oracle的都知道,它是RAT (Oracle Real Application Testing)的一個組件,它可以把一個數據庫的負載在做一些變更之后,在另外一個的數據庫或平臺上去負載重演,看這負載在你升級前后或者硬件更換前后有什么差別.在這里,第一個難題就是DB Replay是11g的一個新特性,而目前我們的庫版本為9i的,所以需要打上一個patch,因此我們要求Oracle全球研發幫我們出一個9i版本的patch,經分析這個patch跟我們目前數據庫補丁有沖突,所以我們花了很長時間去做這種補丁沖突的分析,一層層的抽絲剝繭,最終找到那些產生沖突的patch,把這些不重要的沖突patch拿走.
第二個難題就是我們要在新的11g版本上去安裝patch,這又是另一套原則.大家可以看到,我們先是做了一個補丁列表的篩選,是Oracle發布的Patch Set Update(PSU),還有一些Critical Patch Update(CPU),都作為我們的待選.待選patch的會和已有的、已打的patch做一些補丁沖突分析,如果有沖突的話,那就看它是否關鍵.兩個相比較,看到底哪一個更關鍵一些,我們會留下更為關鍵的一個.如果沒有沖突,直接加入到我們的補丁列表,做成一整套補丁實施方案,這樣我們就能知道未來的系統是什么樣的數據庫版本以及需要打上什么樣的補丁集信息.
第二個選擇比努力更重要的是功能測試.系統每一次的功能版本變更都有一個定型期,因為我們這個事情差不多進行了半年,定型期里面,每發一次版本變更都要同時在9i和11g的平臺上功能驗證通過,我們才能去發布,這是為了保證整個升級運行期軟件版本的一致性,也是為了讓它升級以后不會出問題.
第三個就是性能測試,這是最復雜的地方.我們利用DB Replay抓取9i的負載在11g的環境去重現,那性能的好壞怎么判斷呢?我們先在11g的環境里面去回放這個負載,看它的性能是否下降,如果沒有下降,我們就會把這些Top SQL抓起來,用11g的另外一個新特性,叫SQL plan management(簡稱SPM),去把它的執行計劃固化下來.
固化之后,我們會將這些SQL的執行計劃導入到11g的生產環境中,保證在系統升級前后生產計劃是沒有改變的.如果是性能下降,假如不需要通過代碼改變就可以進行優化的,我們會通過DBA、開發人員等人工優化,把它也用SPM固化下來,同樣導入到生產環境.對于那些沒有辦法簡單地加Hint或通過改變關鍵字次序等進行調優的代碼,就需要開發參與進行代碼的改造.當開發修改代碼時,也是要兩邊調度,同時在9i和11g的版本上進行性能驗證,兩邊都驗證通過之后才能導入生產.
這是整個投產方案的架構設計,看起來比較復雜.我們提用了兩套完全一樣的架構,9i里面有同城的DG,也有遠程的DG,因為這個數據庫太核心,太重要了.同樣的,在升級過程中,我們不允許出一點差錯,所以在11g的投產環境中也有完整的一套11g的預投產、預生產環境,它的同城DG、遠程DG是完全一樣的.
這里面用了三種不同的存儲技術.第一種存儲技術就是11g新生產環境是和原來9i的同城容災是做存儲層面的同步,即存儲LUN級別的同步;第二種存儲技術是利用HDS的一種GAD存儲同步技術,使11g新生產和11g新同城容災不斷地在做數據同步,第三種存儲技術是9i遠程容災與11g新同城容災之間通過SVC實現存儲同步,而這11g新同城容災也就是用于將來的11g的遠程容災環境.
我們還有MIS COW以及DEP COW的補充,用于獲取一些數據采集產生一些報表,所以這里面用了很多種技術,目的就是不去在一個完整的環境中去做升級,也就是說我們不會先去升生產再去搭建一套同城容災、遠程容災,因為這樣的過程中產生的一些RPO、RTO和風險是無法規避的.
我們剛開始就已經在做存儲全量同步,然后也用了HDS GAD在做存儲同步,遠程容災用了SVC存儲同步,升級中我們會把它進行一個存儲的分離,然后本地升級,把剛才提到的一些SPM去導入,然后遠程容災是通過級聯升級,這樣我就會在升級以后出來兩套,一套是9i的環境,一套是11g的環境.升級后我們會把11g產生的數據改變通過OGG同步到9i,所以在任何情況下都可以去回退,而且是完整環境的回退.
這個過程中,我們用了半年,在這半年的時間里,我們首先要構造分析基線,也就是剛才提到的——用DB Replay去回放生產壓力.第一步,我們是在11g的環境里把它的優化器參數和統計信息仍然保留9i的,那么SQL相當于在運行在9i的環境中產生執行計劃及執行情況(因為這是跟當前運行9i的生產環境最接近的),我們會抓取一個基線,并會把它的Top SQL拿下來.
接下來,我們會把11g環境里面的優化器參數和統計信息修改成11g的,再去回放一次負載,比較兩方面的差異,也把它的Top SQL抓取下來,我們這時候也用到SPA,即Oracle RAT中的一個組件SPA(sql performance analyze),DB Replay在整個過程中的作用是回放整個負載,可以觀察數據庫有沒有異常的等待事件,有沒異常消耗高的SQL等,讓你從整體上去判斷.而SPA,是幫你逐條分析SQL,執行計劃有沒有改變,如果有改變,它的buffer gets是升高還是降低,CPU TIMES是升高還是降低等.如果它的性能下降了,是由于什么原因,這些就需要你做進一步深入分析,也就是說Oracle RAT的兩個組件SPA和DB Replay在這期間發揮著不一樣的功能.
在抓取了這些SQL之后,我們就要逐條、逐條地去看,包括一些去重,因為數據量太大了,最初抓取過來的有50多萬條SQL,去重后還有14萬條,后面我們把這14萬條再去分類,該給開發的就給開發,該給DBA的就給DBA去優化,一層一層的優化,才能保證最后上線投產的順利進行.當我們非常有把握或者性能非常穩定的時候,才會去投產.也就是說,我們總共分析了14萬條.
關于SQL語句呢,我不細講,這里提幾個點和例子.首先是綁定變量,就像剛剛提到的固化執行計劃是需要已使用綁定變量的,否則它每條SQL語句都不一樣,這些SQL也就無法共用固化過執行計劃,在這過程中我們發現很多這類的SQL語句.尤其在in里面非常多,要么就是跟個數不一樣,要么就是值輸入不一樣,兩種情況都可能導致固化過的執行計劃發揮不了作用,而這類SQL無法簡單地改造成綁定變量,所以我們進行了改寫,以保證我們通過SPM固化執行計劃達到固化的效果,第一是改寫成綁定變量,第二是將IN寫法改寫成union all這種寫法.通過這兩種手段,去優化它的SQL語句.
第二個例子是隱式轉換.這是因為ibatis有個類型Timestamp與數據庫中的字段類型不一樣導致的,我們也是進行了一些優化.通過在應用代碼中增加cast函數來降低數據精度,并在長期方案中,針對date類型,應用必須傳入string格式,并在XML中使用to_date()函數進行轉換.
第三個例子是復雜視圖.在9i的時候, filter條件可以先在VIEW上過濾再和其他表關聯,但11g必須先實例化VIEW,再進行filter條件過濾,對此,我們在v$sql中查詢VIEW相關的代碼,同時將VIEW拆開,分別和VIEW之外的表進行關聯查詢,最后再合并結果集.
這是幾個比較典型的案例.
做了這么多,耗時6個月,最終的決戰時刻終于到來!這中間涉及到很嚴密的組織架構.有總指揮,然后運營團隊和業務團隊怎么去配合,運營團隊怎么做好深度監控、怎么通知業務團隊準備好升級后的驗證,如果發生問題,應該怎樣去做回退決策,都有哪些人員當時投產、包括投產后要到場值守,這些都要做好.還有要事先做好升級的序列和決策點,哪些點是必須要決策回退,以及性能監控的指標和頻率的提前制定.
本次升級變更的總指揮就是我,當時從最早的解決問題到最終的投產成功,我有60個小時沒有睡覺.基礎架構團隊,像剛才提到的,有主機和存儲的配合.還有DBA團隊、開發測試團隊、運營團隊、業務驗證團隊,大家都是“擰住一股繩,心往一處使”,才能讓這個“只許成功,不許失敗”的項目務必成功.我們只能接受一次失敗,不能接受第二次失敗.
然而,即便我們考慮得非常周密,在投產前還是出了小小的插曲.在投產前的72小時,本來我們是想跟生產環境做存儲同步的,即11g新環境是跟9i生產環境同步的,并且存儲技術已跟廠商確認過沒有問題,而且我們還怕影響白天的業務,專門計劃存儲層數據同步在第一天先做一半,等到第二天過了白天業務的高峰后,晚上再拉起來,用兩個晚上完成存儲同步,這也和廠商確認過,他們也覺得沒問題,但還是發生了問題.后來臨時改變方案,我覺得這也是敏捷運維的一個思想,改為從同城容災進行存儲全量數據同步,這樣就對生產環境沒有影響,但我們的方案就變得更加復雜.這是第一個小插曲.
另外一個是在投產前的32小時,發生了一個大的事務在運行.沒有人能評估出這個事務還有多少時間可以結束,那怎么辦?只能當機立斷去kill這個事務.這個事務當時產生了很多的回滾,回滾是需要時間的,根據當時的速度需要98個小時,但離升級還只有32小時,根本來不及.我們整個準備了半年的升級一年就只有這么一次,如果錯過了,就相當于今年的升級就要告吹了,而以后也仍按照3T的速度來增長,也不太可能再做這個升級.這也是我為什么60個小時不睡覺的原因.升級部門到了總部,告訴我,必須等到事務回滾完才能升級,因為采用的是本地升級.他沒給出什么方法,我這邊無論是調回滾的定期發布,還是調一次回滾的安全數,在別的數據庫里面都是有效的,但對這個數據庫完全沒效.
最后我發現它主要的問題出在db file sequential read上,怎么辦?發現它在回滾的過程中有一個materialized view log,而這個materialized view log所有數據文件只在一個存儲卷里.在這一個卷上我想到用FLASH閃存去替換這一個存儲卷,但這需要冒很大風險,和第一個我剛剛提到的存儲同步故障是有關聯的,第一個已引發了生產故障,然后這個又要在這個生產環境上去做存儲同步,這甚至是冒著被炒魷魚的風險,我沒有告訴其他人,自己做的這個決策.我覺得做領導就該這樣,你只要勇敢做,并敢于承擔.
所以,將物化視圖所在的文件卷替換成Flash閃存,加快db file sequential read的效率后,最終發現回滾速率提升了5倍.同時連夜把一些存儲的同事從凌晨三點鐘叫到公司,啟用存儲Cache預熱功能,將物化視圖和物化視圖log緩存到內存中,發現回滾速率又提升了3倍.終于趕在升級前的6個小時,回滾完畢,來得及去做升級這個動作.
最終在投產后,所幸實施過程是非常順利的.在投產后,高峰期業務吞吐量整整提升了大概25%,批量作業效率提升了5-25倍不等,系統前端響應時間平均提升30%以上,單個SQL效率提升5-9000倍不等.主機的CPU運行從升級前的60%,有時業務高峰甚至達到70-80% ,現在升級后CPU運行在20-30%左右.整個效果看起來還是非常好的.
通過本次升級我想說的是,這里面用到的一些思想和方法,其中包括一些敏捷運維的思想,是可以借鑒到以后同類數據庫產品的升級,也可以用到其他的如主機、存儲等領域的變更或更新換代.這就是我全部的分享,希望能對大家有所啟發.
文章來自微信公眾號:DBAplus社群
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4243.html