mysql在線修改表結構大數據表的風險與解決辦法概括

整理這篇文章的原因:php

互聯網應用會頻繁加功能,修改需求。那麼表結構也會常常修改,加字段,加索引。在線直接在生產環境的表中修改表結構,對用戶使用網站是有影響。html

之前我一直爲這個問題頭痛。固然那個時候不須要我來考慮,雖然咱們沒專門的dba,他們數據量比咱們更大,那這種問題也會存在。因此我很想看看業界是怎麼作的,我想尋找有沒有更高級的方案,呵呵,讓我以爲每次開發一個新功能,我在線加字段都比較糾結。後來只知道,不清楚在何時,無心中看到一個資料介紹online-schema-change這個工具,因而順便搜出了很多東西。後來逐漸發現騰訊,淘寶他們都會存在這種問題,我發現解決思路都差很少。具體看完我這篇概括的文章mysql

 

 

 

因爲mysql在線ddl(加字段、加索引等修改表結構之類的操做)過程以下:linux

 A.對錶加鎖(表此時只讀)
B.複製原表物理結構
C.修改表的物理結構
D.把原表數據導入中間表中,數據同步完後,鎖定中間表,並刪除原表
E.rename中間表爲原表
F.刷新數據字典,並釋放鎖web

 

 

在這個過程當中會鎖表。形成當前操做的表沒法寫入數據,影響用戶使用。因爲須要複製原表的數據到中間表,因此表的數據量越大,等待的時候越長,卡死在那裏(用戶被拒絕執行update和insert操做,表現就是延遲了一直在等待)。sql

其實就是對錶加了個排它鎖,這個時候其餘用戶只能讀表的數據,不能寫。想具體體驗一下是什麼效果,我之前測驗對mysql的表加鎖,操做的時候是如何的:http://www.cnblogs.com/wangtao_20/p/3463435.htmlshell

 

平時進行修改表的結構,更改字段,新增字段,更改字段名稱通常都是經過ALTER TABLE  TABLENAE 語法進行修改的。對於測試庫,在線小表或者併發訪問不是很大的狀況是OK。可是若是是在線大表。那就很麻煩。因爲表數據量大,複製表須要比較長的時間,在這個時間段裏面,表是被加了鎖的(寫鎖),加寫鎖時其餘用戶只能select表不能update、insert表。表數據量越大,耗時越長。數據庫

 

因此,對於數據量大的表,數量很大。在線修改表結構一直是一個頭痛的問題,由於互聯網應用的一大特色不能影響用戶正常使用,不然用戶會慢慢流失掉。安全

 

 

有些公司碰到的表數據很小,幾萬到幾十萬行數據一張表,可能還不會遇到應用卡死的問題。因此咱們網站在跑,開發個新功能,須要加個新字段,常常是直接操做不會影響什麼(況且只是延遲寫入操做而已,呵呵)服務器

看這幾篇文章就知道了:

一、http://wiki.hexnova.com/pages/viewpage.action?pageId=2031684 mysql在線修改表字段形成的鎖表

二、http://hidba.org/?p=795

三、好比就有人專門在加字段以前進行測驗mysql是否複製表,以減低應用卡死的風險:http://www.cnblogs.com/zuoxingyu/archive/2013/03/28/2986715.html

拷貝表結構,而後插入少許的數據。去修改表結構。看影響的行。若是爲0,則表示不會拷貝中間表的方式

 

 

 

目前業界實踐出了一些成熟的解決辦法

一、不少公司之前的作法是:停掉mysql服務器來修改表結構。而後進行滾動式更新。好比不少臺mysql服務器。先修改主服務器的表結構,把這臺服務器停掉來更新(通常多臺主服務器,讓其餘主服務器提供服務)。等到更新完,就滾動到從服務器(在此以前是其餘從服務器提供服務的)。其實想一想發現有個弊病:修改表結構要等到很長時間才能生效。mysql服務器越多,就須要的時間越長。那我能夠理解:假設須要幾天,那只有等到更新完畢。才能把代碼丟上去,由於表結構沒有更新完畢,新的程序操做新的字段會出錯的。

 

從馮大輝那篇文章那裏據說,Facebook數千臺MySQL服務器在過去增長個索引須要幾個月的滾動升級(後來他們本身開發了後面提到的工具,只須要幾天)

 

可以停掉mysql服務器來修改字段,這就好辦,時間長也無所謂,呵呵,至少用戶不會使用你網站的時候卡死吧。可是互聯網應用每每不能影響用戶使用,因此不少公司儘可能是在凌晨的時候進行操做(這個時候訪問用戶少,對用戶影響就小)

好比像這個例子:http://www.mysqlops.com/2011/03/30/myisam-innodb.html

表的數據量上億。要把表的存儲引擎從myisam改成innodb(我以爲存儲結構都不一樣了,轉換須要時間更長),可是他是停掉mysql服務器操做的

阿里巴巴的馮大輝分享中也提到,業務應用大,需求就會頻繁變化。因此就常常涉及到修改數據庫字段,在線的調整字段是要考慮不少的問題的。做者認爲,目前沒有特別的方法來解決這個問題(技術是適應需求變化,支撐運營的)。他說豆瓣對此也很頭痛,只能把服務器短暫的停一下。

 

二、測驗法。加字段,加索引,先在測試環境模擬測試一下須要多長時間。省得服務器生產環境正式加的時候,應用卡死了,好有個預期準備。

我記得之前在a公司,表數據量也上千萬,壓根就沒這種測驗吧,大白天,就直接加字段和索引,反正我也不知道前臺影響如何,當時我也沒這個經驗,況且我也不是技術負責人,呵呵,技術負責人都沒不清楚這個,我那就更加沒了,那個技術經理是作企業級開發的,跟web開發環境和思惟方式是不一樣的,他不清楚會存在這些影響吧,再說,當時在加的時候無法湊巧用戶投訴說,網站沒法下單了啊,沒這麼巧的狀況。其實從我如今理解角度來看,我絕對會更加嚴格點。

 

前面也提到了,國外有人研究修改表結構會不會複製一張臨時表,就看"rows affected 「的值。若是爲0,則表示不會拷貝中間表的方式,這樣子就很快的。我沒試過

 

三、使用專門的輔助工具。一些公司開發了本身的內部工具來輔助進行。好比facebook。

另外騰訊的技術也介紹了他們本身定製的tmysql進行在線加字段的實現原理:

http://www.zhdba.com/mysqlops/2013/09/14/mysql-innodb-online-ddl/

 

facebook本身開發的工具,官網:

http://bazaar.launchpad.net/~mysqlatfacebook/mysqlatfacebook/tools/files/head:/osc

 

 

----------------------------------------------------------------------

我記得好像最早是facebook進行了方案創新(呵呵,當你的遇到的是複雜問題,沒有人解決過就只能先創造新的技術方案了),當時馮大輝專門寫了一篇,其餘文章介紹他們的創新。其餘工具都是跟這個思路差很少的。不過我下載了facebook官網的,是用php實現的。沒具體看。由於下載的包裏面都是php文件。

 

 

總的來講,這些工具大體的理大同小異:表結構的修改在建立的一張新表中執行(這樣不須要鎖定原表了,也就不會影響mysql提供服務),更爲關鍵的是解決了一個問題,當這個間隔時間內,用戶在使用mysql,對錶數據進行了更新怎麼辦?

 

工具的解決辦法思路是,在原表中建立幾個觸發器針對uptate、delete 、insert操做都記錄下來,這樣子把對原表的操做記錄下來,方便更新到新創建的臨時表中中去。

 

 

聽過豆瓣網的架構變遷分享會中提到,他們之前在這方面也吃過苦頭的,一張很大的表(好比上千萬),在線加個索引,因爲數據量大,整個應用就卡死了。

其實有時候卡幾個小時可能都很正常。死鎖了嘛。另外對臨時表要進行復制數據,創建這個臨時表也須要時間嘛。

 

他們如今用的辦法是:先拷貝一張如出一轍的表,數量也是差很少,先在這張表上面測試,看看須要多長時間。若是幾分鐘,是在能夠接受的時間範圍內,就能夠。若是幾個小時就不行了。這樣子提前預先知道。

另外,也使用了online-schema-change這個工具。

 

關於online-schema-change

是percona推出的一個針對mysql在線ddl的工具

percona是一個mysql分支維護公司,專門提供mysql技術服務的。個人理解,相似於linux的分支redhat公司

官網下載地址爲:http://www.percona.com/redir/downloads/percona-toolkit/2.2.1/percona-toolkit-2.2.1.tar.gz

 

騰訊,淘寶,百度這些公司多少都有本身開發的工具來解決這個頭痛的問題。

 

 

另外,mysql5.5企業版是支持在線ddl了,不過企業版要收費嘛

 

MySQL 5.6改進了安全功能,例如對關鍵配置文件和用戶密碼的加密方式,可是對InnoDB的提高才是大新聞。使用該存儲引擎的最後一個主要障礙即是缺乏全文索引,可是如今這個問題已經不復存在了。

該版本還爲InnoDB引入了在線DDL,DBA必定會很是喜歡這個功能。增長、重命名和刪除列等經常使用的操做能夠和併發查詢同時執行。儘管可能涉及到一些數據的複製或重組,可是大多數在線DDL操做都可以就地執行。

相關文章
相關標籤/搜索