全程回放:100T核心資料庫升級歷險記
本文根據汪洋老師在〖2016 Gdevops全球敏捷運維峰會廣州站〗現場演講內容整理而成。
講師介紹
汪洋,從事Oracle相關開發運維工作20年。現任平安科技資料庫技術部總監,負責資料庫技術引入,資料庫產品選型、架構設計、規範制定,開發、測試、生產環境運維等工作。近年,對開源資料庫技術以及DBaaS產生濃厚興趣,一直致力於相關的研究和引入工作。
本次分享大綱:
- 我們的困境和挑戰
- 選擇比努力更重要
- 十月磨一劍
- 最終的決戰時刻今天給大家帶來的分享為《平安產險核心DB升級記》,為什麼選擇“資料庫升級”這個主題來分享呢?首先,一方面我是做資料庫出身的,另一方面,我認為資料庫的升級是一個相對複雜的系統化工程。在這中間,它幾乎要運用到資料庫領域的所有知識,包括管理、備份恢復、容災、監控等,而且這個過程中,該怎麼做升級的準備,如何保證真正的實施方案的順利進行,實施之後如何對它進行監控,以及萬一有預想不到的風險,怎麼去順利回退等等。不單單這樣,它還包括主機的一些儲存、配置,整個流程的東西都需要考慮。這是我選擇這個主題的第一個原因。第二個原因,為什麼是“平安產險”這個資料庫?因為這個9i版本的資料庫在當時可以說是全世界最大的,它有達100多TB的資料容量。它不光是產險最核心的資料庫,並且幾乎產險之外的所有子系統也都在這個資料庫裡面。綜合以上這些因素,構成了這個系統的複雜性。第三個原因,就是五年前我們曾經失敗過一次,所以這個資料庫一直是我們心中的一根刺,心口上永遠的痛,我們一直想把它拔掉。最後,它是從9i升級到11g,可能大家會覺得這是個老生常談的問題,都談了很多年了,而且它也不是升級到最新的版本12c。但它是我從業以來最複雜的一次資料庫升級,裡面用到的一些思想和方法能夠提煉出來,用到不光是Oracle資料庫,也可以用到其他資料庫,甚至不單是資料庫裡面的,也可以運用到其他領域。所以藉此機會分享出來,希望能夠給大家一些借鑑。
一、我們的困境和挑戰
1、業務系統特點介紹
正如前面提到的,它是全球最大的Oracle 9i OLTP資料庫,甚至連原廠的工程師都不敢碰它,覺得這個任務似乎不可能完成。剛剛也說了,五年前我們曾經失敗過一次,那時它才只有10個TB,五年之後,業務資料量變成了110個TB,現在每個月仍在以3TB的速度往上增長,而且是9i版本。眾所周知,9i是個非常老的產品,它可能在設計的時候就沒想過去執行這麼大的一個線上資料庫。
我們看到,它的業務資料量有110TB+,每秒的事務量是2000+,大家可能覺得這事務量不是很高,因為現在都是一萬或十幾萬事務量,但我想告訴大家的是,保險不同於其他行業,它的每個事務都需要涉及到非常複雜的計算後才能提交,所以不同系統的TPS事務量代表的意義是不一樣的。對於產險資料庫來說,它已有的資料量已經是非常高的了,五年前只是現在的1/7,五年後翻了7倍。此外,它每天處理的SQL量有50多萬,基本上支撐著平安產險95%以上的業務。如果萬一發生問題,造成的影響與損失可想而知。
2、當前面臨的問題
- 獲得Oracle產品的Premier Support支援
首先,Oracle 9i版本的延展服務在2011年的7月已經到期了,所以出了問題會怎樣?如果大家用Oracle的話,出了問題,還是可以通過請求GCS (Oracle 全球技術支援)來幫你解決,但如果是新Bug的話,它是不會讓O染成了研發介入開發新patch的,它只能有一些Workaround去幫你規避。如果連Workaround都沒有,那你就只能像踩著鋼絲一樣,天天擔心自己會不會遇到這些新的Bug。假如真的遇到了,也得自己想辦法如何去規避。其實執行這麼多年,我們也通過一些已知的辦法去規避,但這始終不是長久之計。基於這些原因,必須要去升級。
- 解決硬體擴充套件的瓶頸
第二個是硬體擴充套件的瓶頸。它不光是資料庫本身廠商的不支援, 更是強調一個生產圈的不支援,包括它的主機、作業系統都不再服務支援。如現在我們這個新購的主機上只能執行Solaris 11,而Solaris 11 又只認證Oralce 11g以後版本的資料庫,所以不及時升級的話,新採購回來的硬體只能認證比它高的版本,你仍繼續用9i,發生問題時,廠商是沒有辦法解決的,甚至你要冒風險去執行在一個不被認證的作業系統上。還有就是剛才提到的硬體的儲存,我們的資料庫有110TB,而資料量每個月仍在以3T的速度往上增長,而舊的整個儲存最大的容量也就130TB,很快就會達到它的瓶頸。
- 緩解DB效能不穩定的風險
我們在2013-2014年出現了三次UIOC(ugency incident office center),相當於一個作戰史,一共發生了三次,而且每次都與latch: cache buffers chains等待事件相關。其實在9i裡面我們感覺已經沒有一個很有效的辦法可以解決這個問題了,而在更早之前,從2009-2014年間更出現了12次重大事件,其中5次與執行計劃突變有關,這些都是我們用9i時遇到過的問題,急需把它升級為11g。
- 提升技術人力的價值投入
維護9i所投入的人力成本是非常大的。為什麼這麼說呢?因為9i是一個比較舊的技術,很多時候我們的解決手段都必須在更高的版本上去實現,而在9i上做一個技術的變更非常複雜,你要考慮得非常細緻,很多變更不能通過線上操作。如果升級到11g,不光可以釋放一部分的人力,還能把這部分的人力投入到更有價值的事情上去。
3、系統變更要求
我們平時資料庫升級一般遵循的都是一次只做一個變更,但這次情況不同,就像前面提到的受限於硬體、儲存等多個瓶頸,我們一次做了四個變動,這也是為什麼這次升級如此複雜的原因之一。其中,作業系統是從Solaris 10升級到了Solaris 11,DB版本從9.2.0.5升級到了11.2.0.4,主機硬體從M9000升級到T5-4,儲存硬體是從高階SAN變更成了快閃記憶體。現在快閃記憶體是未來儲存的趨勢。
以上這些都是我們在做方案時提出的挑戰和要求。
二、選擇比努力更重要
如果一開始的選擇就是錯的,即使後面你do things right,最後的結果也不一定是對的。因此在升級之前,我們要做出正確的選擇。
1、實施過程設計
這是方案大致的流程。首先要走基礎的硬體上架和基準的測試,比如說,儲存的IO能力能不能達到我的要求,雖然理論上快閃記憶體是要比以前高階SAN要強很多,但沒有經過實際測試過,也是無法確定的,所以需要自己做一遍測試。主機呢,我們也是把真正的生產系統切換到新的主機上進行試執行一次,看T5-4到底是不是要比M9000要好,避免發生我們預期不到的事情。經過這樣一輪測試,我們才有信心、鄭重地做硬體架構升級後的生產執行平臺。接下來,一方面是做效能測試,一方面是要做功能方面的迴歸測試,最後還要聯調再做一次終極的效能驗證。做完之後,使用者接受、開發接受,然後再做系統真實的投產上線和執行。
首先我們碰到的第一個難題就是DB Replay,用過Oracle的都知道,它是RAT (Oracle Real Application Testing)的一個元件,它可以把一個數據庫的負載在做一些變更之後,在另外一個的資料庫或平臺上去負載重演,看這負載在你升級前後或者硬體更換前後有什麼差別。在這裡,第一個難題就是DB Replay是11g的一個新特性,而目前我們的庫版本為9i的,所以需要打上一個patch,因此我們要求Oracle全球研發幫我們出一個9i版本的patch,經分析這個patch跟我們目前資料庫補丁有衝突,所以我們花了很長時間去做這種補丁衝突的分析,一層層的抽絲剝繭,最終找到那些產生衝突的patch,把這些不重要的衝突patch拿走。
2、軟體補丁方案設計
第二個難題就是我們要在新的11g版本上去安裝patch,這又是另一套原則。大家可以看到,我們先是做了一個補丁列表的篩選,是Oracle釋出的Patch Set Update(PSU),還有一些Critical Patch Update(CPU),都作為我們的待選。待選patch的會和已有的、已打的patch做一些補丁衝突分析,如果有衝突的話,那就看它是否關鍵。兩個相比較,看到底哪一個更關鍵一些,我們會留下更為關鍵的一個。如果沒有衝突,直接加入到我們的補丁列表,做成一整套補丁實施方案,這樣我們就能知道未來的系統是什麼樣的資料庫版本以及需要打上什麼樣的補丁集資訊。
3、功能測試方案設計
第二個選擇比努力更重要的是功能測試。系統每一次的功能版本變更都有一個定型期,因為我們這個事情差不多進行了半年,定型期裡面,每發一次版本變更都要同時在9i和11g的平臺上功能驗證通過,我們才能去釋出,這是為了保證整個升級執行期軟體版本的一致性,也是為了讓它升級以後不會出問題。
4、效能測試方案設計
第三個就是效能測試,這是最複雜的地方。我們利用DB Replay抓取9i的負載在11g的環境去重現,那效能的好壞怎麼判斷呢?我們先在11g的環境裡面去回放這個負載,看它的效能是否下降,如果沒有下降,我們就會把這些Top SQL抓起來,用11g的另外一個新特性,叫SQL plan management(簡稱SPM),去把它的執行計劃固化下來。
固化之後,我們會將這些SQL的執行計劃匯入到11g的生產環境中,保證在系統升級前後生產計劃是沒有改變的。如果是效能下降,假如不需要通過程式碼改變就可以進行優化的,我們會通過DBA、開發人員等人工優化,把它也用SPM固化下來,同樣匯入到生產環境。對於那些沒有辦法簡單地加Hint或通過改變關鍵字次序等進行調優的程式碼,就需要開發參與進行程式碼的改造。當開發修改程式碼時,也是要兩邊排程,同時在9i和11g的版本上進行效能驗證,兩邊都驗證通過之後才能匯入生產。
5、投產上線架構設計
這是整個投產方案的架構設計,看起來比較複雜。我們提用了兩套完全一樣的架構,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和風險是無法規避的。
6、投產實現方案設計
我們剛開始就已經在做儲存全量同步,然後也用了HDS GAD在做儲存同步,遠端容災用了SVC儲存同步,升級中我們會把它進行一個儲存的分離,然後本地升級,把剛才提到的一些SPM去匯入,然後遠端容災是通過級聯升級,這樣我就會在升級以後出來兩套,一套是9i的環境,一套是11g的環境。升級後我們會把11g產生的資料改變通過OGG同步到9i,所以在任何情況下都可以去回退,而且是完整環境的回退。
三、十月磨一劍
1、效能分析迭代
這個過程中,我們用了半年,在這半年的時間裡,我們首先要構造分析基線,也就是剛才提到的——用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萬條。
2、繫結變數改造
關於SQL語句呢,我不細講,這裡提幾個點和例子。首先是繫結變數,就像剛剛提到的固化執行計劃是需要已使用繫結變數的,否則它每條SQL語句都不一樣,這些SQL也就無法共用固化過執行計劃,在這過程中我們發現很多這類的SQL語句。尤其在in裡面非常多,要麼就是跟個數不一樣,要麼就是值輸入不一樣,兩種情況都可能導致固化過的執行計劃發揮不了作用,而這類SQL無法簡單地改造成繫結變數,所以我們進行了改寫,以保證我們通過SPM固化執行計劃達到固化的效果,第一是改寫成繫結變數,第二是將IN寫法改寫成union all這種寫法。通過這兩種手段,去優化它的SQL語句。
3、隱式轉換改造
第二個例子是隱式轉換。這是因為ibatis有個型別Timestamp與資料庫中的欄位型別不一樣導致的,我們也是進行了一些優化。通過在應用程式碼中增加cast函式來降低資料精度,並在長期方案中,針對date型別,應用必須傳入string格式,並在XML中使用to_date()函式進行轉換。
4、複雜檢視改造
第三個例子是複雜檢視。在9i的時候, filter條件可以先在VIEW上過濾再和其他表關聯,但11g必須先例項化VIEW,再進行filter條件過濾,對此,我們在v$sql中查詢VIEW相關的程式碼,同時將VIEW拆開,分別和VIEW之外的表進行關聯查詢,最後再合併結果集。
這是幾個比較典型的案例。
四、最終的決戰時刻
1、投產組織工作
做了這麼多,耗時6個月,最終的決戰時刻終於到來!這中間涉及到很嚴密的組織架構。有總指揮,然後運營團隊和業務團隊怎麼去配合,運營團隊怎麼做好深度監控、怎麼通知業務團隊準備好升級後的驗證,如果發生問題,應該怎樣去做回退決策,都有哪些人員當時投產、包括投產後要到場值守,這些都要做好。還有要事先做好升級的序列和決策點,哪些點是必須要決策回退,以及效能監控的指標和頻率的提前制定。
2、投產人員架
本次升級變更的總指揮就是我,當時從最早的解決問題到最終的投產成功,我有60個小時沒有睡覺。基礎架構團隊,像剛才提到的,有主機和儲存的配合。還有DBA團隊、開發測試團隊、運營團隊、業務驗證團隊,大家都是“擰住一股繩,心往一處使”,才能讓這個“只許成功,不許失敗”的專案務必成功。我們只能接受一次失敗,不能接受第二次失敗。
3、投產前小插曲
然而,即便我們考慮得非常周密,在投產前還是出了小小的插曲。在投產前的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個小時,回滾完畢,來得及去做升級這個動作。
4、投產執行分析
最終在投產後,所幸實施過程是非常順利的。在投產後,高峰期業務吞吐量整整提升了大概25%,批量作業效率提升了5-25倍不等,系統前端響應時間平均提升30%以上,單個SQL效率提升5-9000倍不等。主機的CPU執行從升級前的60%,有時業務高峰甚至達到70-80% ,現在升級後CPU執行在20-30%左右。整個效果看起來還是非常好的。
小結
通過本次升級我想說的是,這裡面用到的一些思想和方法,其中包括一些敏捷運維的思想,是可以借鑑到以後同類資料庫產品的升級,也可以用到其他的如主機、儲存等領域的變更或更新換代。這就是我全部的分享,希望能對大家有所啟發。
文章來自微信公眾號:DBAplus社群