前兩天系統(tǒng)的一張明細(xì)表的主鍵字段超出了限制范圍,引發(fā)了一次生產(chǎn)事故定罢。由于是底層服務(wù)使用的表笤虫,導(dǎo)致公司多個(gè)業(yè)務(wù)線系統(tǒng)無法使用,屬于比較重大的生產(chǎn)事故祖凫,分享給大家琼蚯,避免出現(xiàn)此類低級(jí)又重大的生產(chǎn)問題。
事故反饋
首先反饋出異常的是服務(wù)的告警機(jī)制蝙场,告警群中出現(xiàn)大量MySQL異常告警:
然后一線業(yè)務(wù)使用方在工作群中反饋系統(tǒng)不可用凌停,然后我們趕快緊急排查并解決問題。你懂的售滤,在你排查解決問題的過程中各個(gè)相關(guān)的同事都會(huì)過來問候你一下:產(chǎn)品經(jīng)理、上級(jí)領(lǐng)導(dǎo)台诗、運(yùn)營完箩、其它服務(wù)調(diào)用方....此時(shí),你面不改色拉队,鎮(zhèn)定自若弊知,其實(shí)內(nèi)心(手動(dòng)狗頭)...
事故原因
導(dǎo)致此次線上事故的原因是系統(tǒng)的一張老表(很早的一張表)的主鍵是int類型,表中數(shù)據(jù)存儲(chǔ)的數(shù)據(jù)量(行數(shù))達(dá)到了int值的上限:2147483647粱快。你可以想象到這個(gè)表有多大:上百GB秩彤!
你可能會(huì)覺得這種問題好low笆宥蟆!你說還債也好漫雷,報(bào)應(yīng)也罷瓜富,我們就當(dāng)一次日后吹牛逼的話題吧。針對(duì)此次事故降盹,重要的是我們解決問題的過程以及從中獲取的經(jīng)驗(yàn)
解決方案
方案1
刪除表中的舊數(shù)據(jù)与柑,設(shè)置表的主鍵自增從0開始,此方案溝通后不行蓄坏。原因:
- 生產(chǎn)數(shù)據(jù)不能隨便刪除价捧,可能有未知隱患
- 表中數(shù)據(jù)量太大,這張表日增數(shù)據(jù)量近百萬級(jí)涡戳,從幾百G的大表中刪除百萬數(shù)據(jù)(需夠一天使用)结蟋,這個(gè)操作將會(huì)消耗大量的數(shù)據(jù)庫實(shí)例的資源,進(jìn)而影響其它業(yè)務(wù)渔彰,不可接受
方案2
把表的主鍵類型由int改為bigint嵌屎,對(duì)應(yīng)的代碼model由Integer改為Long。此處可能是大家有些著急吧胳岂,犯了一個(gè)流程性的問題:我們開發(fā)認(rèn)為代碼層面方案沒問題编整,在熱火朝天的修改,結(jié)果表結(jié)構(gòu)的變更工單提交給DBA審批乳丰,不通過掌测,表數(shù)據(jù)量太大,變更表結(jié)構(gòu)極其耗時(shí)产园,可能小時(shí)級(jí)汞斧,方案廢棄
方案3
創(chuàng)建一張新表,結(jié)構(gòu)和原表一樣(只是把主鍵類型換為bigint)什燕,主鍵自增從2300000000開始(為了和舊表數(shù)據(jù)區(qū)分)粘勒,修改業(yè)務(wù)代碼:
- 代碼中,新數(shù)據(jù)寫入到新建的表中
- 代碼中查數(shù)據(jù)屎即,從新表和老表中一起查詢庙睡,合并返回。之所以新舊表一起查詢技俐,是因?yàn)槭鹿拾l(fā)生時(shí)有的業(yè)務(wù)已經(jīng)產(chǎn)生過明細(xì)數(shù)據(jù)乘陪,然后又被業(yè)務(wù)人員重新操作,新數(shù)據(jù)存在新表中
最終采用此方案雕擂,修復(fù)上線啡邑,問題解決。
方案后續(xù)處理
- 后續(xù)將舊表的數(shù)據(jù)同步到新表中井赌,恢復(fù)單表查詢
- 表數(shù)據(jù)歸檔
復(fù)盤反思
- 數(shù)據(jù)庫表的主鍵建議采用bigint類型(一般性規(guī)約谤逼,除非是簡(jiǎn)單的配置表用int)
- 對(duì)老系統(tǒng)贵扰,可以定期巡查相關(guān)數(shù)據(jù)表(有告警最好),提早發(fā)現(xiàn)遺留問題流部,提前解決
- 處理緊急問題戚绕,思路很重要,不能盲目修改