
問題域:資料量大、并發量高場景,如何在流量低峰期,平滑實施表結構變更?
畫外音,一般來說,是指增加表的屬性,因為:
(1)如果是減column,更新程式不使用即可;
(2)如果是修改column,程式相容性容易出問題;
首先,一起看下有哪些常見方案。
方案一:線上修改表結構。
畫外音:alter table add column
資料量大的情況下,鎖表時間會較長,造成拒絕服務,一般不可行。 方案二:通過增加表的方式擴充屬性,通過外鍵join來查詢。舉個例子,對:
t_user(uid, c1, c2, c3)
想要擴充屬性,可以通過增加一個表實作:
t_user_ex(uid, c4, c5, c6)
資料量大的情況下,join性能較差,一般不可行。 方案三,通過增加表的方式擴充,通過視圖來屏蔽底層複雜性。同上,視圖效率較低,一般不使用視圖。
方案四,揍産品經理,阻止她修改需求。...
方案五,提前預留一些reserved字段,加列可複用這些字段。
這個方案可行,但如果預留過多,會造成空間浪費。
方案六,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;
擴充字段完成,整個過程不需要鎖表,可以持續對外提供服務。 操作過程中需要注意:(1)變更過程中,最重要的是沖突的處理,一條原則,以觸發器的新資料為準,這就要求被遷移的表必須有主鍵(這個要求基本都滿足);(2)變更過程中,寫操作需要建立觸發器,是以如果原表已經有很多觸發器,方案就不行(網際網路大資料高并發的線上業務,一般都禁止使用觸發器);
(3)觸發器的建立,會影響原表的性能,是以這個操作必須在流量低峰期進行; pt-online-schema-change是DBA必備的利器,比較成熟,在網際網路公司使用廣泛,要了解更詳細的細節,亦可以Google一下。
任何脫離業務的架構設計都是耍流氓。
本文轉自“架構師之路”公衆号,58沈劍提供。