表空間瘦身之重建表

參數(shù)

1)innodb_file_per_table = OFF? ?表示的是表的數(shù)據(jù)放在系統(tǒng)共享表空間

2)innodb_file_per_table =?ON??每個(gè) InnoDB 表數(shù)據(jù)存儲在一個(gè)以 .ibd 為后綴的文件

中宪塔。從 MySQL 5.6.6 版本開始磁奖,它的默認(rèn)值就是 ON 了。

不論使用 MySQL 的哪個(gè)版本某筐,都將這個(gè)值設(shè)置為 ON比搭。因?yàn)椋粋€(gè)表單獨(dú)存儲為一個(gè)文件更容易管理南誊,而且在你不需要這個(gè)表的時(shí)候身诺,通過 drop table 命令,系統(tǒng)就會直接刪除這個(gè)文件抄囚。而如果是放在共享表空間中霉赡,即使表刪掉了,空間也是不會回收的幔托。

在刪除整個(gè)表的時(shí)候穴亏,可以使用 drop table 命令回收表空間。

數(shù)據(jù)刪除流程:

InnoDB 里的數(shù)據(jù)都是用 B+ 樹的結(jié)構(gòu)組織的。


B+ 樹索引示意圖

假設(shè)嗓化,我們要刪掉 R4 這個(gè)記錄锅劝,InnoDB 引擎只會把 R4 這個(gè)記錄標(biāo)記為刪除。如果之后要再插入一個(gè) ID 在 300 和 600 之間的記錄時(shí)蟆湖,可能會復(fù)用這個(gè)位置故爵。但是,磁盤文件的大小并不會縮小隅津。

InnoDB 的數(shù)據(jù)是按頁存儲的诬垂,那么如果我們刪掉了一個(gè)數(shù)據(jù)頁上的所有記錄,整個(gè)數(shù)據(jù)頁就可以被復(fù)用了伦仍。

如果相鄰的兩個(gè)數(shù)據(jù)頁利用率都很小结窘,系統(tǒng)就會把這兩個(gè)頁上的數(shù)據(jù)合到其中一個(gè)頁上,另外一個(gè)數(shù)據(jù)頁就被標(biāo)記為可復(fù)用充蓝。

如果我們用 delete 命令把整個(gè)表的數(shù)據(jù)刪除呢隧枫?結(jié)果就是,所有的數(shù)據(jù)頁都會被標(biāo)記為可復(fù)用谓苟。但是磁盤上官脓,文件不會變小。

delete 命令其實(shí)只是把記錄的位置涝焙,或者數(shù)據(jù)頁標(biāo)記為了“可復(fù)用”卑笨,但磁盤文件的大小是不會變的。也就是說仑撞,通過 delete 命令是不能回收表空間的赤兴。這些可以復(fù)用,而沒有被使用的空間隧哮,看起來就像是“空洞”桶良。

實(shí)際上,不止是刪除數(shù)據(jù)會造成空洞沮翔,插入數(shù)據(jù)也會陨帆。

如果數(shù)據(jù)是按照索引遞增順序插入的,那么索引是緊湊的鉴竭。但如果數(shù)據(jù)是隨機(jī)插入的歧譬,就可能造成索引的數(shù)據(jù)頁分裂。


插入數(shù)據(jù)導(dǎo)致頁分裂

可以看到搏存,由于 page A 滿了瑰步,再插入一個(gè) ID 是 550 的數(shù)據(jù)時(shí),就不得不再申請一個(gè)新的頁面 page B 來保存數(shù)據(jù)了璧眠。頁分裂完成后缩焦,page A 的末尾就留下了空洞读虏。

更新索引上的值,可以理解為刪除一個(gè)舊的值袁滥,再插入一個(gè)新值盖桥。不難理解,這也是會造成空洞的题翻。

經(jīng)過大量增刪改的表揩徊,都是可能是存在空洞的。所以嵌赠,如果能夠把這些空洞去掉塑荒,就能達(dá)到收縮表空間的目的。而重建表姜挺,就可以達(dá)到這樣的目的齿税。

重建表


改鎖表 DDL

花時(shí)間最多的步驟是往臨時(shí)表插入數(shù)據(jù)的過程,如果在這個(gè)過程中炊豪,有新的數(shù)據(jù)要寫入到表 A 的話凌箕,就會造成數(shù)據(jù)丟失。因此词渤,在整個(gè) DDL 過程中牵舱,表 A 中不能有更新。也就是說掖肋,這個(gè) DDL 不是 Online 的仆葡。

MySQL 5.6 版本開始引入的 Online DDL,重建表的大概流程如下:

1.?建立一個(gè)臨時(shí)文件志笼,掃描表 A 主鍵的所有數(shù)據(jù)頁;

2.?用數(shù)據(jù)頁中表 A 的記錄生成 B+ 樹把篓,存儲到臨時(shí)文件中纫溃;

3. 生成臨時(shí)文件的過程中,將所有對 A 的操作記錄在一個(gè)日志文件(row log)中韧掩,對應(yīng)

的是圖中 state2 的狀態(tài)紊浩;

4. 臨時(shí)文件生成后,將日志文件中的操作應(yīng)用到臨時(shí)文件疗锐,得到一個(gè)邏輯數(shù)據(jù)上與表 A 相

同的數(shù)據(jù)文件坊谁,對應(yīng)的就是圖中 state3 的狀態(tài);

5. 用臨時(shí)文件替換表 A 的數(shù)據(jù)文件滑臊。


Online DDL

可以看到口芍,與 改鎖表 DDL過程的不同之處在于,由于日志文件記錄和重放操作這個(gè)功能的存在雇卷,

這個(gè)方案在重建表的過程中鬓椭,允許對表 A 做增刪改操作颠猴。這也就是 Online DDL 名字的來

源。

Online DDL小染,alter 語句在啟動的時(shí)候需要獲取 MDL 寫鎖翘瓮,但是這個(gè)寫鎖在真正

拷貝數(shù)據(jù)之前就退化成讀鎖了。為什么要退化呢裤翩?為了實(shí)現(xiàn) Online资盅,MDL 讀鎖不會阻塞增刪改操

作。

而對于一個(gè)大表來說踊赠,Online DDL 最耗時(shí)的過程就是拷貝數(shù)據(jù)到臨時(shí)表的過程呵扛,這個(gè)步

驟的執(zhí)行期間可以接受增刪改操作。所以臼疫,相對于整個(gè) DDL 過程來說择份,鎖的時(shí)間非常短。對業(yè)務(wù)來

說烫堤,就可以認(rèn)為是 Online 的荣赶。

需要補(bǔ)充說明的是,上述的這些重建方法都會掃描原表數(shù)據(jù)和構(gòu)建臨時(shí)文件鸽斟。對于很大的

表來說拔创,這個(gè)操作是很消耗 IO 和 CPU 資源的。因此富蓄,如果是線上服務(wù)剩燥,你要很小心地控

制操作時(shí)間。如果想要比較安全的操作的話立倍,我推薦你使用 GitHub 開源的 gh-ost 來

做灭红。

Online 和 inplace區(qū)別

改鎖表,我們把表 A 中的數(shù)據(jù)導(dǎo)出來的存放位置叫作 tmp_table口注。這是一個(gè)臨時(shí)表变擒,是在 server 層

創(chuàng)建的。

Online寝志,根據(jù)表 A 重建出來的數(shù)據(jù)是放在“tmp_file”里的娇斑,這個(gè)臨時(shí)文件是 InnoDB

在內(nèi)部創(chuàng)建出來的。整個(gè) DDL 過程都在 InnoDB 內(nèi)部完成材部。對于 server 層來說毫缆,沒有把

數(shù)據(jù)挪動到臨時(shí)表,是一個(gè)“原地”操作乐导,這就是“inplace”名稱的來源苦丁。

重建表的這個(gè)語句 alter table t engine=InnoDB,兽叮,其實(shí)隱含的意思是:

alter table t engine=innodb,ALGORITHM=inplace;

跟 inplace 對應(yīng)的就是拷貝表的方式了芬骄,用法是:

alter table t engine=innodb,ALGORITHM=copy;

當(dāng)你使用 ALGORITHM=copy 的時(shí)候猾愿,表示的是強(qiáng)制拷貝表,對應(yīng)的流程就是圖改鎖表 DDL?的操

作過程账阻。

inplace 跟 Online 是不是就是一個(gè)意思蒂秘?

其實(shí)不是的,只是在重建表這個(gè)邏輯中剛好是這樣而已淘太。

如果我要給 InnoDB 表的一個(gè)字段加全文索引姻僧,寫法是:

alter table t add FULLTEXT(field_name);

這個(gè)過程是 inplace 的,但會阻塞增刪改操作蒲牧,是非 Online 的撇贺。

如果說這兩個(gè)邏輯之間的關(guān)系是什么的話,可以概括為:

1)?DDL 過程如果是 Online 的冰抢,就一定是 inplace 的松嘶;

2)?反過來未必,也就是說 inplace 的 DDL挎扰,有可能不是 Online 的翠订。添加全文索引(FULLTEXT index)和空間索引 (SPATIAL index) 就屬于這種情況。

optimize table遵倦、analyze table 和 alter table 這三種方式重建表的區(qū)別:

1.?從 MySQL 5.6 版本開始尽超,alter table t engine = InnoDB(也就是 recreate)默認(rèn)是online DDL

2.?analyze table t 其實(shí)不是重建表,只是對表的索引信息做重新統(tǒng)計(jì)梧躺,沒有修改數(shù)據(jù)似谁,這個(gè)過程中加了 MDL 讀鎖;

3.?optimize table t 等于 recreate+analyze掠哥。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巩踏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子续搀,更是在濱河造成了極大的恐慌蛀缝,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件目代,死亡現(xiàn)場離奇詭異,居然都是意外死亡嗤练,警方通過查閱死者的電腦和手機(jī)榛了,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來煞抬,“玉大人霜大,你說我怎么就攤上這事「锎穑” “怎么了战坤?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵曙强,是天一觀的道長。 經(jīng)常有香客問我途茫,道長碟嘴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任囊卜,我火速辦了婚禮娜扇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘栅组。我一直安慰自己雀瓢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布玉掸。 她就那樣靜靜地躺著刃麸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪司浪。 梳的紋絲不亂的頭發(fā)上泊业,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機(jī)與錄音断傲,去河邊找鬼脱吱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛认罩,可吹牛的內(nèi)容都是我干的箱蝠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼垦垂,長吁一口氣:“原來是場噩夢啊……” “哼宦搬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起劫拗,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤间校,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后页慷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體憔足,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年酒繁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滓彰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娶视,到底是詐尸還是另有隱情僵刮,我是刑警寧澤筐眷,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布末荐,位于F島的核電站潜的,受9級特大地震影響狰域,放射性物質(zhì)發(fā)生泄漏邦蜜。R本人自食惡果不足惜依鸥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望畦徘。 院中可真熱鬧毕籽,春花似錦、人聲如沸井辆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杯缺。三九已至蒸播,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間萍肆,已是汗流浹背袍榆。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留塘揣,地道東北人包雀。 一個(gè)月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像亲铡,于是被迫代替她去往敵國和親才写。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348