運維不背鍋!持續(xù)兩年數(shù)據(jù)庫“0故障”的運維優(yōu)化之道
運維團隊天天忙著應(yīng)付各種異常,長久處于高壓狀態(tài)下。本文作者將分享這兩年他對一些運維問題的分析和團隊管理的方法。
大家好,我是來自平安科技數(shù)據(jù)庫技術(shù)部運維團隊的劉書安,從 2014 年開始,配合平安集團的互聯(lián)網(wǎng)金融轉(zhuǎn)型。
我們運維的數(shù)據(jù)庫從單純的 Oracle 數(shù)據(jù)庫轉(zhuǎn)向多種數(shù)據(jù)庫的運維,當(dāng)前管理的各類數(shù)據(jù)庫的實例已經(jīng)超過了一萬個。在這種情況下,我們連續(xù)兩年保持了數(shù)據(jù)庫零故障的狀態(tài)。
事實上在之前,運維團隊也是天天忙著應(yīng)付各種異常,長久處于高壓狀態(tài)下。之后經(jīng)過我們團隊一系列的優(yōu)化和改造,目前系統(tǒng)已穩(wěn)定很多。這期間也確實發(fā)生了很多事情。
接下來就跟大家簡單介紹一下我們這兩年對一些運維問題的分析和團隊管理的方法,拋磚引玉一下。
問題解決
首先我們從這張圖說起:
這個是扁鵲向魏王介紹他們?nèi)值艿尼t(yī)術(shù):
- 扁鵲自己是在病人病入膏肓?xí)r用虎狼之藥將對方救活。
- 扁鵲的二哥是在別人生小病時將人治愈。
- 扁鵲的大哥則是在病情未發(fā)時鏟除病因讓人避免生病。
在扁鵲看來,三個人的醫(yī)術(shù)排序應(yīng)該是:大哥>二哥>扁鵲;但在世人眼里卻是:扁鵲>二哥>大哥。
我比較認同扁鵲的觀點,因為我一直都覺得 DB 的運維人員不應(yīng)該只是背鍋俠,而是應(yīng)該把自己當(dāng)成醫(yī)生來對待問題,不只是關(guān)注問題的解決,更需要多關(guān)注如何避免問題的發(fā)生。
我們在數(shù)據(jù)庫異常時去解決問題,別人可能會認為我們是高手,能把問題解決好、事情處理掉。
但實際上這時的運維已經(jīng)是一個被動式的處理,即便我們用了最快的手段去解決,故障已經(jīng)發(fā)生了,可能還造成了比較嚴重的影響。
如果我們能提前發(fā)現(xiàn)這些問題并解決掉,就能避免很多故障和影響的發(fā)生。因此在我看來,運維相對高明的手段應(yīng)該是:在做架構(gòu)或設(shè)計時就把能想到的問題預(yù)先解決掉,確保系統(tǒng)的可拓展性和高可用性。
運維也應(yīng)該多從架構(gòu)的角度去考慮問題,并將這些問題提前解決好,而非被動地等待問題發(fā)生后才去解決。
接下來和大家介紹我們團隊解決的三個案例,以及之后我們通過什么方式避免問題的發(fā)生:
案例一
這是我們在 2016 年解決的案例,當(dāng)時 Oracle 數(shù)據(jù)庫的版本是 11.2.0.4,這種數(shù)據(jù)庫使用 SPM 固化 TOP SQL 的執(zhí)行計劃,確保系統(tǒng)的穩(wěn)定。
當(dāng)時異常的問題是,幾乎每次發(fā)完大的版本后,已有的功能都會多少受到影響,有一些語句的執(zhí)行計劃會發(fā)生異常。
我們發(fā)現(xiàn),絕大多數(shù)語句都和這個語句是類似的,中間有一個 SKIP SCAN(跳躍式掃描),很明顯可以看出它是一個輸入時間(對著用戶的),有一個范圍查詢。
所以我們當(dāng)時就基本判斷問題出在這里了,使用的解決方案是通過重新固化執(zhí)行計劃來選擇好的執(zhí)行計劃。
接著就開始分析問題產(chǎn)生的原因。
對于索引跳躍式掃描而言,在一般情況下,如果運維索引的***個列沒有用到,當(dāng)它開始使用到第二個列時,就只能用跳躍式的方法去進行一個索引掃描。
而在分析問題原因時,因為類似的語句比較多,我們當(dāng)時在固化了幾十條后,發(fā)現(xiàn)還有源源不斷的類似語句出現(xiàn),就考慮到問題可能并沒有那么簡單。
所以我們又進行了進一步分析,***發(fā)現(xiàn)可能是索引的統(tǒng)計信息有問題。于是我們就重新收集了索引的統(tǒng)計信息,至此,類似的語句問題才算是解決了。
但其實這個問題并沒有徹底結(jié)束:
我們在處理完后又重新分析了這個索引的問題,發(fā)現(xiàn)索引***列是一個空值,但不知道是誰在空列和輸入時間上建了一個符合索引,導(dǎo)致這個索引有可能會被使用。
發(fā)現(xiàn)問題后,我們就查詢了這個索引的訪問方式,看看是否全都是 INDEX SKIP SCAN。
后來發(fā)現(xiàn),基本上訪問這個索引的語句都用的是這種索引跳躍式掃描,所以我們當(dāng)時就把這個索引設(shè)置為不可用,后面把它刪除了。
類似的索引,我們當(dāng)時處理了有三個,之后這個系統(tǒng)就沒有再出現(xiàn)這樣類似的問題。
SPM 也是一種固化執(zhí)行計劃的方式,但為什么在這個庫里,SPM 會失效呢?
之后我們分析了它的原因:是因為每次發(fā)版本時,有可能會多查一些字段,導(dǎo)致語句發(fā)生變化。
SPM 這類的固化執(zhí)行計劃的方式都和語句有強關(guān)聯(lián),只要語句上有一個小小的改動,都會導(dǎo)致固化的方式失效。這也是每次更新版本語句都會發(fā)生異常的原因之一。
之后我們繼續(xù)分析,為什么這個時間索引有這種類似問題?
這是我們之前整理的一個案例分析的原因:我們在做索引的范圍查詢時,它的選擇率公式如下 :
但是在不同情況下,比如這種右側(cè)索引,比如創(chuàng)建時間、更新時間、輸入時間,我們寫入數(shù)據(jù)都是用 sysdate 寫入的,那么它永遠都在索引列的右側(cè),類似這種方式是往里面插入數(shù)據(jù)的。
然而我們統(tǒng)計信息的收集又不是一個實時收集的,主要是對一些大表,比如一個一千萬的表可能要到 10%,也就是 100 萬的 DMR 量;更大的表的DMR量會更大。
這就會導(dǎo)致我們的統(tǒng)計信息和當(dāng)前的值永遠是過時的,就會產(chǎn)生下面的問題。
對于這三個查詢來說:***個查詢發(fā)生在有效范圍內(nèi),所以它可以反映出一個比較真實的數(shù)據(jù);第二個查詢也可以反映一部分。
但第三個查詢就相當(dāng)于完成一個超范圍的查詢,計算出一個很低的值,這樣就會導(dǎo)致我們的語句偏異常。
更坑的是在 OLPP 系統(tǒng)里,新數(shù)據(jù)查詢的幾率永遠比老數(shù)據(jù)的大,越新的數(shù)據(jù)被訪問的幾率越高,這也導(dǎo)致我們的語句每次都會出現(xiàn)異常的情況。
發(fā)現(xiàn)這些問題后,我們立即展開了一個行動,就是把數(shù)據(jù)庫里所有與時間索引相關(guān)的字段都提取一下。
然后定期修改索引字段上面的 HIGH VALUE,統(tǒng)計信息里面的 HIGH VALUE,就能避免出現(xiàn)這種問題。
如上圖所示,是一個范圍查詢的情況,即在一個索引前導(dǎo)列的區(qū)別,類似于我們在創(chuàng)建時間和 OWNER 之間建索引。
如果把創(chuàng)建時間放在前面,把 OWNER 放在后面就是***種情況;如果把 OWNER 放在前面,把 CREATED 放在后面就是第二種情況。
現(xiàn)在來分析這兩個不同索引的區(qū)別:
當(dāng)我們把創(chuàng)建時間放在前面時,有一個很大的問題,我們通過時間字段去查詢時很難做到等值查詢,即不可能去發(fā)現(xiàn)每分每秒插入的值。
對于這種查詢,我們一般都使用范圍查詢,比如查一個月或一天、一周的數(shù)據(jù)。
所以大家可以看到,如果我在這個語句內(nèi)查這一分鐘、這一天 DBMGR 創(chuàng)建的情況,在***個索引里它整個范圍都會涉及到,隨后取相關(guān)聯(lián)的三個值。
但是在第二個索引里,三個值是連在一起的,因為 DBMGR 是有序的,時間也是有序的,它們就可以完成只涉及到自己相關(guān)值的值。
這里面還有一些細小的區(qū)別:如果我先進行范圍查詢,后做等值查詢,對于這樣的索引,F(xiàn)ilter 時就會多做一個 Filter 步驟。
但如果把這個順序調(diào)整一下,就不會有這種情況。所以我們在做這種符合索引創(chuàng)建的時候,就一定要盡量把等值查詢的放在前面。
之前有一個說法:在選擇符合索引的前導(dǎo)列時,要把選擇率比較低的值放在前導(dǎo)列。
但我們覺得這個說法是不完善的:比如對于一個時間字段而言,一天有 86400 秒,100 天就可能有 800 多萬的不同值,一年會有更多不同值。
可如果把這個作為前導(dǎo)列,有時候是不適合的,因為對它來說,有可能我們是需要查詢一天或一個月的數(shù)據(jù),而一年有 365 天,或者說十二個月。因此更準確的說法應(yīng)該是把查詢條件中選擇率低的列做為復(fù)合索引的前導(dǎo)列。
所以通過這個案例,我們就把運維問題的解決分成了三個步驟:
- 快速解決問題,確保應(yīng)用恢復(fù)。對于運維人員來說,恢復(fù)應(yīng)用是***位的。
- 看問題是不是重復(fù)性發(fā)生的。比如前面說的案例一,如果我們當(dāng)時的處理方案僅是固化執(zhí)行計劃,或是收集統(tǒng)計信息,你沒有辦法保證它以后不會再出現(xiàn)類似的情況。
如果我們使用的是收集統(tǒng)計信息的方式,可能再過一個月或兩個月,這種情況又會再次發(fā)生,所以根本的解決方案是找到這個問題發(fā)生的原因,確保這次問題解決后不會再復(fù)發(fā)。
- 避免問題,看這個問題是否屬于共性問題、其他庫里有沒有類似問題。如果有類似問題,就要形成一種規(guī)范,去避免這種問題的發(fā)生。
尤其是對于一些新的應(yīng)用來說,只有當(dāng)你制定規(guī)范、讓開發(fā)遵守后,后續(xù)才會減少類似問題的發(fā)生,不然就會演變成我們一邊解決問題,新問題又源源不斷發(fā)生的情況,***我們只能不斷地去解決這種重復(fù)發(fā)生的問題。
我記得之前有一個案例就是共性問題:當(dāng)時是在一個實際的庫里,我們分析發(fā)現(xiàn)它存在內(nèi)存泄漏的問題,但并沒有馬上開始處理,結(jié)果第二天另一個庫也發(fā)生內(nèi)存泄漏,于是我們不得不緊急重啟。
當(dāng)時我們分析出問題是由某一個 Bug 導(dǎo)致后,就搜索那個 Bug 相關(guān)的信息,發(fā)現(xiàn)早在兩三年前(2014 年)已經(jīng)有同事解決了這個問題。
只不過在另一個庫里還打了相應(yīng)的 PATCH 來解決問題,但就是因為沒有把這個問題推廣到所有系統(tǒng)里,排查是否其他庫也存在這個問題而引起的。
從那之后我們就特別注意這種共性問題,如果每個系統(tǒng)、每個問題都要發(fā)生一次,代價實在是太大了。
所以我們盡可能在發(fā)現(xiàn)共性問題后就解決掉,盡量排除其他庫也發(fā)生類似問題的情況。
案例二
第二個案例是一個版本為 12.1.0.2 的 Oracle 數(shù)據(jù)庫,每到晚上總會不定時地主機 CPU 持續(xù)到 100%,應(yīng)用同時會創(chuàng)建大量的數(shù)據(jù)到數(shù)據(jù)庫中。
當(dāng)時我們的應(yīng)急方案是把這種相關(guān)的等待時間全部批量 Kill 掉,因為這些系統(tǒng)是在比較核心的庫里,基本上每個系統(tǒng)被 Kill 掉的進程有幾千個,代價還是比較大的。
后來這個問題發(fā)生兩次后,我們開始著手重點分析問題,通過 ASH 分析發(fā)現(xiàn),出現(xiàn)這個異常等待是因為一個很簡單的語句—— SELECT USER FROM SYS.DUAL。
之后我們就通過這個語句來一步步關(guān)聯(lián), 看到底是哪個地方調(diào)用的,結(jié)果發(fā)現(xiàn)是在一個應(yīng)用用戶的登錄 TRIGGER 中的用戶判斷步驟。
這個 USER 是 Oracle 的內(nèi)部函數(shù),但就是這么簡單的一個語句,就讓整個庫都 Hang 住了。
然后我們開始分析原因,我們通過 ASH 發(fā)現(xiàn)該語句在我們恢復(fù)應(yīng)用前有重新加載的過程。
當(dāng)時我們懷疑是硬件導(dǎo)致的,就通過這種方式去分析,結(jié)果發(fā)現(xiàn)是在晚上 10 點時被 Oracle 的自動任務(wù)做了一個統(tǒng)計信息的自動收集。
收集完后,又因為它是一個登錄的 Trigger,用戶在不斷登錄,在做登錄解析時這個語句就沒辦法解析,所以才導(dǎo)致用戶源源不斷地卡在那里。
而應(yīng)用是需要新建連接的,新建的連接又無法進到庫里面,就會導(dǎo)致連接數(shù)越來越多,全都卡在那里。***我們通過鎖定 dual 表統(tǒng)計信息的收集來從根本上解決這個問題。
案例三
第三個案例有兩個問題,但后來我們發(fā)現(xiàn)這兩個問題是由相同的原因引起的。
我們有一個數(shù)據(jù)庫是從 10.2.0.5.X 升級到 10.2.0.5.18 版本,升級后會不定時出現(xiàn) cursor:pin 相關(guān)的一些等待。
其實出現(xiàn) cursor:pin 是很正常的,因為這個數(shù)據(jù)庫的負載比較高,變化也較高,但問題是它是在升級之后出現(xiàn)的。運營認為這是升級之后出現(xiàn)的異常,我們就開始著手分析問題的原因。
第二個問題是我們在應(yīng)急時發(fā)現(xiàn)的,有時異常出現(xiàn)時,某個庫里有些語句的執(zhí)行次數(shù)會特別高,甚至 15min 能達到上億次,這對于一個正常的業(yè)務(wù)系統(tǒng)來說,出現(xiàn)這么高的執(zhí)行頻率是不正常的。
之后我們就去分析這些問題,發(fā)現(xiàn)這兩個問題有相同的一些點:比如語句中間出現(xiàn)了個函數(shù)調(diào)用;比如說這個情況下,A 表如果訪問的數(shù)據(jù)量較大時,這些函數(shù)就有可能被調(diào)用很多次。
我們發(fā)現(xiàn),有一個語句,它執(zhí)行一次可能會出現(xiàn)十幾萬次的函數(shù)調(diào)用。如果在調(diào)用的過程中,關(guān)聯(lián)的那張表的執(zhí)行計劃發(fā)生了變化,比如說A表走了一個全程掃描,那可能會出現(xiàn)幾千萬次的函數(shù)調(diào)用。
當(dāng)時我們也總結(jié)了一些關(guān)于通過什么樣的方法去快速定位、是否是函數(shù)調(diào)用導(dǎo)致的看法。
在 Oracle 10g 之前確實沒有什么好的辦法,因為它里面沒有一個顯示的關(guān)聯(lián),就可能通過代碼去掃描,去找對應(yīng)的語句。
在 Oracle 11g 后會比較簡單一些,通過 AS 值相關(guān)的 TOP LEVEL SQL ID 就可以直接關(guān)聯(lián)到是哪個語句調(diào)的函數(shù)導(dǎo)致的問題。
這里還有一個問題是函數(shù)調(diào)用。因為它調(diào)用的函數(shù)可能都是特別快的,但次數(shù)又會比較高,性能波動可能帶來比較大的影響。
之前我們有一個案例就發(fā)生在月底高峰,我們當(dāng)時發(fā)現(xiàn)某個數(shù)據(jù)庫中會出現(xiàn)很多 CBC 的等待,后來又發(fā)現(xiàn)有一個小表被頻繁訪問,那個小表就 100 多行數(shù)據(jù),但可能它相關(guān)的語句每隔 15min 就調(diào)用了上千萬次。
其實這么高的并發(fā)下,出現(xiàn)這種 CBC 的等待是很正常的。不過因為它只有 100 多行數(shù)據(jù),且都集中在一個數(shù)據(jù)塊里,所以才導(dǎo)致這個數(shù)據(jù)塊特別熱,就會一直出現(xiàn)這種 CBC 的等待。
于是我們就找辦法解決這個熱塊的問題,但又因為不能在月底沖業(yè)績時停運來做修改。
所以我們就想了一個方案:建一個 PCT FREE 99 的索引,把表所有列的數(shù)據(jù)都包含進去,確保每個索引塊里面只保留了一行數(shù)據(jù),變相地把這 100 多行數(shù)據(jù)分到 100 多個塊里。
做了這個操作后,CBC 相關(guān)的問題被解決了,也順利地撐過了業(yè)務(wù)高峰期,但是第二天月初的報表發(fā)現(xiàn)又掉坑里了。
因為我們在每個月月初需要上報給監(jiān)管的一個報表,這種報表是屬于一個長事務(wù)。
但是它在那個報表里面也是調(diào)了之前優(yōu)化的那個索引,優(yōu)化后的語句雖然降低高峰期 CBC 的等待,但因為它是要訪問 100 多個數(shù)據(jù)塊,單次訪問從 0.25 毫秒變成了 1 毫秒,相當(dāng)于效率降低了 4 倍。
由于報表是一種長事務(wù)的處理,相當(dāng)于那個進程比原來多花了一倍多的時間也沒跑完。
所以之后我們發(fā)現(xiàn)這個問題后,又不得不把那個索引給干掉了,讓它恢復(fù)原來那種狀態(tài)。
尤其是現(xiàn)在對 IT 的要求越來越高,時限的要求也越來越高,很多系統(tǒng)基本都是用這種敏捷的開發(fā)方式盡快地上線。
新系統(tǒng)上線有一個很大的問題就是剛上線時壓力都不會很大、負載也不高,但其實很多問題在開始階段被隱藏了。
等到真正發(fā)生問題時,負載高了或者壓力大了再去解決問題,難度就會比較大一點。
尤其對于數(shù)據(jù)庫來說,數(shù)據(jù)庫量小的時候,比如說 300、500M 的數(shù)據(jù),這個表格怎么整改都很簡單,但等到這個表漲到 300、500G 甚至 1、2T 時再想去做這個表數(shù)據(jù)類的整改,難度就會大很多。
比如說,我們之前做分期表整改時會用這種在線重定義的方式,但對于一些比較大的表,幾百 G 甚至上 T 的表,再用這種在線重定義的方式,就會遇到各種各樣的 Bug。
后來坑踩多了,我們現(xiàn)在對于大表的分表改造就是先同步歷史數(shù)據(jù)級改造,后做一個數(shù)據(jù)增量,方法會復(fù)雜很多。
但其實如果在開始階段,我們對于這種大表就已經(jīng)設(shè)計好它的分區(qū),尤其在時間索引上,基于時間去做一個分區(qū),可以避免很多問題。
為什么我們的歷史庫里有那么多時間索引?
很大的一個原因是有很多報表是基于時間去查詢的,比如說要查這一個月或者這一天新增的一些數(shù)據(jù)的情況,都需要通過時間的字段去訪問。
我之前就見過很多關(guān)于時間的索引,但***卻因為時間索引的特性,導(dǎo)致系統(tǒng)源源不斷地出現(xiàn)各種各樣的問題。
如果在設(shè)計階段把這些大表提前就設(shè)計成分區(qū)表,完全可以避免這些不必要的問題。
運維管理
因為各個公司具體情況不同,我接下來就簡單介紹一下我司關(guān)于運維管理的一些做法,給大家做個參考。
變更管理
相對來說,我們公司的變更管理比較嚴格,后續(xù)可能會更加嚴格。
變更管控
對于變更管控,比如在白天嚴禁做任何變更,工作時間內(nèi)任何變更都不能做,即便是一些緊急或故障的修復(fù),也是需要通過部門負責(zé)人確認、領(lǐng)導(dǎo)同意后才可以做的,確保風(fēng)險可控。
變更流程
可能每個公司都有變更流程,但我們公司有一個比較特殊的地方。因為一些兼容數(shù)據(jù)庫的要求可能會高一些,流程管控的每個部分都要確保到位。
變更方案
我們的變更方案是每個人要提前去做評審和驗證,包括制定方案的同事和實施操作的同事,就需要變更實施人員提前在一個環(huán)境下做完整的驗證,確保每個步驟都是驗證通過的。
規(guī)范管理
架構(gòu)規(guī)范
我自己之前在做架構(gòu)師時,制定各種各樣的規(guī)范是一項重點的工作??赡苁丘B(yǎng)成習(xí)慣了,現(xiàn)在也和大家一起制定各式各樣的運維規(guī)范。
但我自己感受最深的是:規(guī)范一定要有統(tǒng)一的標準,如果做不到統(tǒng)一就有可能會在后續(xù)產(chǎn)生問題。
比如我們之前有些開發(fā)測試環(huán)境不是那么規(guī)范,現(xiàn)在想改造做自動化時,發(fā)現(xiàn)根本就做不起來,因為每個庫的情況不一樣,自動化的腳本不可能適應(yīng)所有情況來做這種標準化的改造。
把它弄成不標準是很簡單的,但要想把不標準的改成標準的,難度就大了,尤其是在我們已經(jīng)形成習(xí)慣之后。
運維規(guī)范
在 2014 年前,我們做的是純 Oracle 數(shù)據(jù)庫的運維,因為之前建立的是一個傳統(tǒng)的金融企業(yè),運維的都是 Oracle 數(shù)據(jù)庫,但 2014 年后我們逐步轉(zhuǎn)向了互聯(lián)網(wǎng)金融。
因此我們陸續(xù)研究了 MySQL、PG、Redis、MongDB、SQL Server、HBase 等 7、8 種數(shù)據(jù)庫,在運維過程中遇的坑就會比較多。
最初有很多標準,但沒有一個是***的實踐,很多也是根據(jù)業(yè)界、自己的經(jīng)驗制定出來的;還有各種不同的數(shù)據(jù)庫里,不同的團隊制定了不同標準,***就有各種各樣的標準了。
所以我們在運維中會發(fā)現(xiàn)各種各樣的問題,***要強制去做這方面的規(guī)范整改。
而且,之前的標準大部分都沒有經(jīng)過大規(guī)模使用和大規(guī)模負載的驗證,很多標準并不那么統(tǒng)一、規(guī)范和有效。
因此,我們在運維過程中對于這種規(guī)范,還是在不斷地去優(yōu)化和改進,畢竟很多情況在沒有遇到時,你真的是沒有辦法去解決這個問題。
規(guī)范優(yōu)化
舉個例子,最初我們并沒有規(guī)定 Redis 一定要和應(yīng)用放在同一個網(wǎng)絡(luò)區(qū)域,但隨著 Redis 的負載增加,我們發(fā)現(xiàn)防火墻已經(jīng)承受不了。
當(dāng)時平安的 WiFi 剛上線不久,但關(guān)于 Redis 的訪問,幾個實例每秒都有高達上萬次調(diào)用,整個防火墻都撐不住了,還差點導(dǎo)致一個比較嚴重的故障。
在解決這個問題后,我們就制定了一條強制的規(guī)范:Redis 這種高并發(fā)訪問的數(shù)據(jù)庫,一定要和應(yīng)用放在一起,不能有出現(xiàn)跨墻訪問的情況。
所以這個規(guī)范也是不斷去優(yōu)化的,包括我們運維的一些標準。因為在最初創(chuàng)建標準時,我們可能會因為使用時間不長而考慮不到一些問題。
我印象比較深刻的是 MySQL 剛引入時的一個問題,對于軟件的版本沒有明確到小版本。
后來甚至出現(xiàn)有 MySQL 停庫時是 5.6.22 的版本,在維護完成后就被啟動成 5.6.16 的版本。
***是通過不斷地優(yōu)化來確保我們的規(guī)范和實際是相結(jié)合的,避免這種問題的發(fā)生。
人員發(fā)展
團隊意識
關(guān)于團隊這塊,需要提升每個人在團隊中的作用,需要確保團隊里的每個人都是有備份的。如果發(fā)展成離開誰都不行,那對團隊的整體發(fā)展來說是不正常的。
所以我們在安排工作時,對于比較重要的工作,我會盡量不讓熟悉的同事重復(fù)去做,而是盡量讓一些不熟悉的同事參與去做。
之前每走一個資深成員,都會明顯感覺到團隊的整體技能或知識少了一塊。為了避免類似問題的發(fā)生,從 2017 年開始我們就制定了一些策略,讓大家做知識技能的分享,每周抽取兩個下午,每個下午抽取一到兩個小時做分享。
另一個策略是技能的積累,即把我們在工作中遇到和解決的一些問題都錄入問題管理系統(tǒng)。
這樣做有兩個好處:
- 可以把重復(fù)的問題記錄下來,因為我們想要去分析哪些問題是重復(fù)發(fā)生的、哪些是有共性的,就需要有一個這樣的系統(tǒng)去拉對應(yīng)的問題清單,***去解決問題。
- 即便人員流失了,他們之前解決的一些問題和技能也能讓團隊其他人發(fā)現(xiàn),不至于每走一個人就留下一個坑。
所以我們是通過這種手段來盡量避免人員流失或變動給團隊帶來的一些問題。
但說到底,這種事這是沒辦法完全避免的,因為數(shù)據(jù)庫運維有一定的復(fù)雜度,需要依靠不斷地發(fā)生故障、解決故障,包括一些人為失誤來提升。
權(quán)責(zé)分明
我們的輪班人員是 7×24 小時,即上三班的方式來輪班的。之前團隊有一個比較嚴重的問題,當(dāng)一件事情發(fā)生了,輪班人員有可能將問題交接給下一班次;或是升級給其他人后,就覺得與自己沒有關(guān)系了。
還有就是風(fēng)險意識不強,有一些操作沒有評估過影響就開始在生產(chǎn)庫里操作。
當(dāng)時我們也發(fā)生了不少問題,后來在內(nèi)部重點提升兩點意識:責(zé)任人意識和風(fēng)險意識。
首先你需要在生產(chǎn)做措施前,確保要做的操作會有什么影響、導(dǎo)致什么后果,不能在做完后才去想這個問題:比如說我們現(xiàn)在每天變更,都需要提前把腳本和手冊做好,讓值班人員熟悉。
操作會有什么后果?后續(xù)有什么異常會發(fā)生?應(yīng)對方法又是什么?……這些都是需要提前評估好的。
技能提升
關(guān)于技能提升,雖然必要的培訓(xùn)是必不可少的,但我們認為關(guān)鍵還是要靠自己的學(xué)習(xí)、理解和在實踐中的積累,并沒有什么好的捷徑去實現(xiàn),大多時候還是要通過不斷地解決問題、發(fā)現(xiàn)問題甚至包括犯錯的代價來提升的。
劉書安,平安科技數(shù)據(jù)庫技術(shù)部運維團隊經(jīng)理,當(dāng)前任職于平安科技數(shù)據(jù)庫技術(shù)部運維團隊,有十余年的數(shù)據(jù)庫管理經(jīng)驗,有多年數(shù)據(jù)庫架構(gòu)設(shè)計和運維管理經(jīng)驗,熟悉性能調(diào)優(yōu)和故障處理。目前主要負責(zé)平安科技數(shù)據(jù)庫運維的管理工作,團隊負責(zé)運維的數(shù)據(jù)庫種類包括 Oracle、PostgreSQL、MySQL、Redis、MongoDB 等多數(shù)數(shù)據(jù)庫的運維管理工作。