天天看點

幾千萬記錄,資料庫表結構如何平滑變更?

幾千萬記錄,資料庫表結構如何平滑變更?

問題域:資料量大、并發量高場景,如何在流量低峰期,平滑實施表結構變更?

畫外音,一般來說,是指增加表的屬性,因為:

(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沈劍提供。