MySQL 中的共享表空間與獨(dú)立表空間,用哪個(gè)好呢?
我們今天就開(kāi)始學(xué)習(xí) MySQL 中另外一個(gè)非常重要的存儲(chǔ)引擎 InnoDB 了。
要說(shuō) InnoDB,我們就不得不先來(lái)說(shuō)說(shuō)另外一個(gè)比較重要的話題表空間和共享表空間,這也是我們本文的主題。
1.獨(dú)立表空間與共享表空間
對(duì)于 InnoDB 存儲(chǔ)引擎來(lái)說(shuō),它可以將每張表存放于獨(dú)立的表空間,即 tablename.ibd 文件;也可以將數(shù)據(jù)存放于 ibdata 的共享表空間,一般命名是 ibdataX,后面的 X 是一個(gè)具體的數(shù)字。
我們先來(lái)體驗(yàn)看看這兩種有什么區(qū)別。
首先我們執(zhí)行如下代碼可以查看是否開(kāi)啟了獨(dú)立表空間:
- show variables like 'innodb_file_per_table';
可以看到,默認(rèn)情況下,獨(dú)立表空間是開(kāi)啟的。
這個(gè)時(shí)候我們來(lái)創(chuàng)建一個(gè)使用了 InnoDB 引擎的表,如下(默認(rèn)存儲(chǔ)引擎就是 InnoDB):
- create table book(id int,name varchar(255));
創(chuàng)建完成后,我們來(lái)到存放數(shù)據(jù)文件的目錄下,可以看到如下文件:
可以看到,當(dāng)前表被存放在獨(dú)立的 book.ibd 文件中。
存放于獨(dú)立表空間的表都將會(huì)以獨(dú)立文件的方式來(lái)進(jìn)行存儲(chǔ),每一個(gè)表都有一個(gè) .frm 表描述文件(這個(gè)和 MyISAM 引擎一致),還有一個(gè) .ibd 文件,這個(gè)文件包括了單獨(dú)一個(gè)表的數(shù)據(jù)內(nèi)容以及索引內(nèi)容,默認(rèn)情況下它的存儲(chǔ)位置也是在表的位置之中。
接下來(lái)我們執(zhí)行如下代碼,修改 innodb_file_per_table 的值為 OFF,即關(guān)閉獨(dú)立表空間,如下:
關(guān)閉之后,再來(lái)創(chuàng)建新表:
- create table book2(id int,name varchar(255));
新表創(chuàng)建成功之后,此時(shí)我們?cè)偃ケ砟夸浵虏榭次募l(fā)現(xiàn)并沒(méi)有一個(gè)名為 book2.ibd 的文件,說(shuō)明此時(shí)的表已經(jīng)存放于共享表空間了。
那么共享表空間的 ibdata1 文件又在哪里呢?其實(shí)就在 MySQL 存放數(shù)據(jù)庫(kù)的目錄下:
我們可以通過(guò)如下命令查看 ibdata1 的默認(rèn)大小:
- show variables like 'innodb_data_file_path';
可以看到,默認(rèn)大小是 12M。
需要注意的是,innodb_file_per_table 要在創(chuàng)建表之前修改,創(chuàng)建表之后再去修改,是不會(huì)影響已有的表結(jié)構(gòu)的。
2.該用哪一個(gè)?
要搞明白要用哪一種表空間,我們得先明白兩種不同表空間各自的特點(diǎn)。
2.1 獨(dú)立表空間
優(yōu)勢(shì)
- 每張表都有自己獨(dú)立的表空間。
- 每張表的數(shù)據(jù)和索引都會(huì)存儲(chǔ)在自己的表空間中。
- 可以實(shí)現(xiàn)單表在不同的數(shù)據(jù)庫(kù)中移動(dòng)(因?yàn)槊繌埍矶加歇?dú)立的數(shù)據(jù)表文件)。
- 空間可以回收(通過(guò) optimize table 命令實(shí)現(xiàn))。
- 無(wú)論怎么刪除,表空間的碎片不會(huì)太嚴(yán)重影響系統(tǒng)性能。
缺點(diǎn)
- 單表增加過(guò)大。
2.2 共享表空間
優(yōu)勢(shì)
- 可以將表空間分成多個(gè)文件存放到各個(gè)磁盤上(表空間文件大小不受表大小的限制,如一個(gè)表可以分布在不同的文件上)。
- 數(shù)據(jù)和文件放在一起方便管理。
缺點(diǎn)
- 所有的數(shù)據(jù)和索引存放到一個(gè)文件中,這將意味著有一個(gè)很大的文件存在(雖然可以把一個(gè)大文件分成多個(gè)小文件),但是多個(gè)表及索引在表空間中混合存儲(chǔ),這樣當(dāng)一個(gè)表做了大量刪除操作后表空間中將會(huì)有大量的空隙,特別是對(duì)于統(tǒng)計(jì)分析、日志系統(tǒng)這類應(yīng)用而言,最不適合用共享表空間(例如,當(dāng)系統(tǒng)空間不夠用的時(shí)候,我們希望通過(guò)刪除一些無(wú)效數(shù)據(jù)來(lái)騰出來(lái)一些表空間,這個(gè)時(shí)候我們會(huì)發(fā)現(xiàn),如果使用了共享表空間,即使無(wú)效數(shù)據(jù)刪除了,表空間還是還是不會(huì)縮小)。
- 共享表空間管理會(huì)出現(xiàn)表空間分配后不能回縮的問(wèn)題,當(dāng)臨時(shí)建立索引或者臨時(shí)表導(dǎo)致表空間擴(kuò)大后,就是刪除相關(guān)的表也沒(méi)辦法回縮那部分空間了。
- 對(duì)于第二點(diǎn)存在的問(wèn)題,一般使用 mysqldump 導(dǎo)出數(shù)據(jù),然后刪除共享表空間數(shù)據(jù)文件后,再重新導(dǎo)入。
- 由于一個(gè)文件中保存了多個(gè)表數(shù)據(jù),所以并發(fā)操作時(shí)可能會(huì)產(chǎn)生 IO 瓶頸,所以需要頻繁寫(xiě)入的場(chǎng)景并不適合共享表空間。
經(jīng)過(guò)以上的分析,相信小伙伴們已經(jīng)明白了,在實(shí)際項(xiàng)目中,還是首選獨(dú)立表空間比較好,事實(shí)上,從 MySQL5.6 開(kāi)始,獨(dú)立表空間就已經(jīng)成為默認(rèn)選項(xiàng)了。
3.遷移
最后還有一個(gè)問(wèn)題,如果一開(kāi)始創(chuàng)建的是共享表空間,那么還能遷移到獨(dú)立表空間嗎?當(dāng)然可以!參考如下四個(gè)步驟:
- 使用 mysqldump 導(dǎo)出所有數(shù)據(jù)庫(kù)表數(shù)據(jù)。
- 停止 MySQL 服務(wù),修改 innodb_file_per_table 參數(shù),并刪除 InnoDB 相關(guān)文件(如果是主從結(jié)構(gòu),則可以從 Slave 上入手完成這些操作)。
- 重啟 MySQL 服務(wù),重建 InnoDB 共享表空間(此時(shí)里邊就沒(méi)有數(shù)據(jù)了)。
- 重新導(dǎo)入數(shù)據(jù)。
好啦,今天就和小伙伴們聊一聊共享表空間和獨(dú)立表空間,InnoDB 的其他玩法我們后面再繼續(xù)介紹~
本文轉(zhuǎn)載自微信公眾號(hào)「江南一點(diǎn)雨」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系江南一點(diǎn)雨公眾號(hào)。