本應(yīng)該是開開心的開啟美麗的一周创泄,結(jié)果卻在一次驚嚇中開啟了這有點(diǎn)憂桑的一周。
事情是這樣疗涉,就在今天脐帝,大周一的早上八點(diǎn)睜開眼看一眼手機(jī),哐哐的彈了好多告警信息仆百,瞬間就清醒了厕隧,第一時間打開電腦排查問題,并同時聯(lián)系同事一起處理俄周,因?yàn)橐谎劭催^去吁讨,不是個容易解決的問題,于是聯(lián)系我們項(xiàng)目負(fù)責(zé)人峦朗,開啟查看問題的一天建丧。
排查問題完寫了一個總結(jié),這里就也記錄一下吧波势,如果遇到同樣問題的小伙伴翎朱,希望能幫到你,不過更好的是尺铣,看過能引以為戒拴曲,提前發(fā)現(xiàn)并解決問題。
問題記錄如下:
1凛忿、遇到的問題
Mysql 的自增主鍵達(dá)到最大值澈灼,會發(fā)生什么你知道嗎?就在今天,我們線上就發(fā)生了這種問題叁熔。
insert 數(shù)據(jù)就會報(bào)錯委乌,表的id 自增主鍵達(dá)到了最大值。
2荣回、問題分析
總結(jié)來說這算是架構(gòu)上的設(shè)計(jì)問題吧福澡。
先說一下我們目前暴露出來的倆問題:
① Mysql 的自增主鍵默認(rèn)是 int 類型,4 個字節(jié)驹马,一個字節(jié) 8 位革砸,即如果是有符號的位的話,最大值就是(2^31)-1糯累,也就是2147483647算利,基本也就能存儲 20 億數(shù)據(jù)。當(dāng)數(shù)據(jù)達(dá)到千萬上億級別時泳姐,查詢數(shù)據(jù)就會特別特別慢了效拭,所以我們就采取了數(shù)據(jù)歸檔。這里是另外一個坑下面在介紹胖秒。應(yīng)該根據(jù)業(yè)務(wù)數(shù)據(jù)量缎患,分析數(shù)據(jù)的增長情況,提前規(guī)劃進(jìn)行分庫分表阎肝,至少要保證每個表不超過千萬級挤渔。這樣才能保證查詢效率。
② 這里說下上邊提到的另外一個坑:我們的因?yàn)椴樵儽容^慢风题,對表做過幾次數(shù)據(jù)歸檔判导,就是將數(shù)據(jù)寫入一張表中,當(dāng)數(shù)據(jù)量很大時沛硅,就定時將某個時間之前的數(shù)據(jù)寫入另一個表中眼刃,這樣做也是有一些坑的。
Mysql的 delete 并不會真正的刪除磁盤空間摇肌,而只是標(biāo)記相應(yīng)的區(qū)域擂红,在合適的時候還可以再利用。如果要真正騰出磁盤空間還必須使用 optimize table xxx 進(jìn)行磁盤碎片處理围小,但是這個命令會在相應(yīng)的庫下產(chǎn)生一個很大的 #sql-xxx 文件昵骤,此文件的贈長速度特別快,要清除的表越大它的增長速度就越快吩抓,所以不能等磁盤已經(jīng)快滿了才想起來清理涉茧。
而且 optimize 命令會鎖表,一般根據(jù)表的數(shù)據(jù)增長速度和刪除等情況綜合考慮決定 optimize 命令的執(zhí)行頻率疹娶。比如在訪問量最小的時候一個月或者兩個月執(zhí)行一次伴栓。
3、解決辦法
① 修改 id 字段類型,int 改為 bigint(太占空間了钳垮,一個bigint的存儲大小為8字節(jié)) bigint 的大小是8個字節(jié)惑淳,一個字節(jié) 8 位,有符號的最大值就是 2 的 63 次方 -1饺窿。即 bigint 帶符號的范圍是 -9223372036854775808 到 9223372036854775807歧焦。無符號的范圍是 0 到 18446744073709551615。
② 有能力還是分表肚医,有效避免這個問題
③ 將 int 類型設(shè)置為無符號的可以擴(kuò)大一倍
基于以上三種最好的處理方法還是分庫分表绢馍。
4、臨時解決方案
目前我們基于線上的臨時解決方案是新建了一個同結(jié)構(gòu)的表肠套,業(yè)務(wù)數(shù)據(jù)走新表舰涌,查詢兼容舊表