前兩天系統(tǒng)的一張明細(xì)表的主鍵字段超出了限制范圍,引發(fā)了一次生產(chǎn)事故。由于是底層服務(wù)使用的表,導(dǎo)致公司多個(gè)業(yè)務(wù)線系統(tǒng)無(wú)法使用,屬于比較重大的生產(chǎn)事故,分享給大家,避免出現(xiàn)此類(lèi)低級(jí)又重大的生產(chǎn)問(wèn)題。

事故反饋
首先反饋出異常的是服務(wù)的告警機(jī)制,告警群中出現(xiàn)大量MySQL異常告警:

然后一線業(yè)務(wù)使用方在工作群中反饋系統(tǒng)不可用,然后我們趕快緊急排查并解決問(wèn)題。你懂的,在你排查解決問(wèn)題的過(guò)程中各個(gè)相關(guān)的同事都會(huì)過(guò)來(lái)問(wèn)候你一下:產(chǎn)品經(jīng)理、上級(jí)領(lǐng)導(dǎo)、運(yùn)營(yíng)、其它服務(wù)調(diào)用方....此時(shí),你面不改色,鎮(zhèn)定自若,其實(shí)內(nèi)心(手動(dòng)狗頭)...
事故原因
導(dǎo)致此次線上事故的原因是系統(tǒng)的一張老表(很早的一張表)的主鍵是int類(lèi)型,表中數(shù)據(jù)存儲(chǔ)的數(shù)據(jù)量(行數(shù))達(dá)到了int值的上限:2147483647。你可以想象到這個(gè)表有多大:上百GB!
你可能會(huì)覺(jué)得這種問(wèn)題好low?。∧阏f(shuō)還債也好,報(bào)應(yīng)也罷,我們就當(dāng)一次日后吹牛逼的話題吧。針對(duì)此次事故,重要的是我們解決問(wèn)題的過(guò)程以及從中獲取的經(jīng)驗(yàn)
解決方案
方案1
刪除表中的舊數(shù)據(jù),設(shè)置表的主鍵自增從0開(kāi)始,此方案溝通后不行。原因:
- 生產(chǎn)數(shù)據(jù)不能隨便刪除,可能有未知隱患
- 表中數(shù)據(jù)量太大,這張表日增數(shù)據(jù)量近百萬(wàn)級(jí),從幾百G的大表中刪除百萬(wàn)數(shù)據(jù)(需夠一天使用),這個(gè)操作將會(huì)消耗大量的數(shù)據(jù)庫(kù)實(shí)例的資源,進(jìn)而影響其它業(yè)務(wù),不可接受
方案2
把表的主鍵類(lèi)型由int改為bigint,對(duì)應(yīng)的代碼model由Integer改為L(zhǎng)ong。此處可能是大家有些著急吧,犯了一個(gè)流程性的問(wèn)題:我們開(kāi)發(fā)認(rèn)為代碼層面方案沒(méi)問(wèn)題,在熱火朝天的修改,結(jié)果表結(jié)構(gòu)的變更工單提交給DBA審批,不通過(guò),表數(shù)據(jù)量太大,變更表結(jié)構(gòu)極其耗時(shí),可能小時(shí)級(jí),方案廢棄
方案3
創(chuàng)建一張新表,結(jié)構(gòu)和原表一樣(只是把主鍵類(lèi)型換為bigint),主鍵自增從2300000000開(kāi)始(為了和舊表數(shù)據(jù)區(qū)分),修改業(yè)務(wù)代碼:
- 代碼中,新數(shù)據(jù)寫(xiě)入到新建的表中
- 代碼中查數(shù)據(jù),從新表和老表中一起查詢,合并返回。之所以新舊表一起查詢,是因?yàn)槭鹿拾l(fā)生時(shí)有的業(yè)務(wù)已經(jīng)產(chǎn)生過(guò)明細(xì)數(shù)據(jù),然后又被業(yè)務(wù)人員重新操作,新數(shù)據(jù)存在新表中
最終采用此方案,修復(fù)上線,問(wèn)題解決。
方案后續(xù)處理
- 后續(xù)將舊表的數(shù)據(jù)同步到新表中,恢復(fù)單表查詢
- 表數(shù)據(jù)歸檔
復(fù)盤(pán)反思
- 數(shù)據(jù)庫(kù)表的主鍵建議采用bigint類(lèi)型(一般性規(guī)約,除非是簡(jiǎn)單的配置表用int)
- 對(duì)老系統(tǒng),可以定期巡查相關(guān)數(shù)據(jù)表(有告警最好),提早發(fā)現(xiàn)遺留問(wèn)題,提前解決
- 處理緊急問(wèn)題,思路很重要,不能盲目修改