幾千萬記錄,數據庫表結構如何平滑變更?
繼續回答知識星球水友提問。
問題域:數據量大、并發量高場景,如何在流量低峰期,平滑實施表結構變更?
畫外音,一般來說,是指增加表的屬性,因為:
- 如果是減column,升級程序不使用即可;
- 如果是修改column,程序兼容性容易出問題;
首先,一起看下有哪些常見方案。
(1) 方案一:在線修改表結構。
畫外音:alter table add column
數據量大的情況下,鎖表時間會較長,造成拒絕服務,一般不可行。
(2) 方案二:通過增加表的方式擴展屬性,通過外鍵join來查詢。
舉個例子,對:
- t_user(uid, c1, c2, c3)
想要擴展屬性,可以通過增加一個表實現:
- t_user_ex(uid, c4, c5, c6)
數據量大的情況下,join性能較差,一般不可行。
(3) 方案三,通過增加表的方式擴展,通過視圖來屏蔽底層復雜性。
同上,視圖效率較低,一般不使用視圖。
畫外音:至少58到家禁止使用視圖。
(4) 方案四,揍產品經理,阻止她修改需求。...
(5) 方案五,提前預留一些reserved字段,加列可復用這些字段。
這個方案可行,但如果預留過多,會造成空間浪費。
(6) 方案六,pt-online-schema-change
對于MySQL而言,這是目前比較成熟的方案,被廣大公司所使用。
畫外音:我呆過的互聯網公司,數據庫均使用MySQL。
下面仍以用戶表擴展為例,說下這個工具內部的原理與步驟。
假設:
- user(uid, name, passwd)
要擴展到:
- user(uid, name, passwd, age, sex)
第一步,先創建一個擴充字段后的新表:
- user_new(uid, name, passwd, age, sex)
畫外音:就是被擴展后的表。
第二步,在原表user上創建三個觸發器,對原表user進行的所有insert/delete/update操作,都會對新表user_new進行相同的操作;
第三步,分批將原表user中的數據insert到新表user_new,直至數據遷移完成;
第四步,刪掉觸發器,把原表移走(默認是drop掉);
第五步,把新表user_new重命名(rename)成原表user;
擴充字段完成,整個過程不需要鎖表,可以持續對外提供服務。
操作過程中需要注意:
- 變更過程中,最重要的是沖突的處理,一條原則,以觸發器的新數據為準,這就要求被遷移的表必須有主鍵(這個要求基本都滿足);
- 變更過程中,寫操作需要建立觸發器,所以如果原表已經有很多觸發器,方案就不行(互聯網大數據高并發的在線業務,一般都禁止使用觸發器);
- 觸發器的建立,會影響原表的性能,所以這個操作必須在流量低峰期進行;
pt-online-schema-change是DBA必備的利器,比較成熟,在互聯網公司使用廣泛,要了解更詳細的細節,亦可以Google一下。
任何脫離業務的架構設計都是耍流氓。
【本文為51CTO專欄作者“58沈劍”原創稿件,轉載請聯系原作者】