[翻譯] MySQL 之 InnoDB 特性和最佳實(shí)踐

mysql

官方文檔:15.1 Introduction to InnoDB

一、MySQL 之 InnoDB 總體介紹

InnoDB 是 MySQL 中一個(gè)平衡了 高可用搞性能 的通用存儲(chǔ)引擎鳄逾。在 MySQL 8.0 中稻轨,除非通過 my.cnf 配置了默認(rèn)的存儲(chǔ)引擎,或者在 CREATE TABLE 語(yǔ)句中顯式的通過 ENGINE=xxx 指定了別的存儲(chǔ)引擎雕凹,InnoDB 將作為 MySQL 的默認(rèn)存儲(chǔ)引擎殴俱。

1. InnoDB 的明顯優(yōu)勢(shì)
  • InnoDB 的事務(wù)中,DML (Data Manipulation Language) 滿足事務(wù)的 ACID 原則枚抵,支持事務(wù)的提交 (commit) 和回滾 (rollback) 功能线欲,同時(shí)基于災(zāi)難恢復(fù) (crash-recovery) 的能力確保了用戶數(shù)據(jù)的安全性。
  • 更小粒度的 行鎖 和 Oracle 風(fēng)格的一致性讀 (consistent read) 保證了多用戶訪問時(shí)的并發(fā)能力汽摹,提高了整體性能李丰。
  • InnoDB 在磁盤上的數(shù)據(jù)存儲(chǔ)方式,對(duì)主鍵 (primary keys) 查詢做了優(yōu)化逼泣。在每一個(gè)包含主鍵索引趴泌,準(zhǔn)確地說是聚簇索引 (clustered index),的 InnoDB 表中拉庶,聚簇索引以一種 使得主鍵查找 IO 次數(shù)最少 的方式在磁盤上存放數(shù)據(jù)嗜憔。
  • InnoDB 支持外鍵 (foreign key) 限制,進(jìn)一步保證了數(shù)據(jù)的完整性 (integrity)砍的。外鍵限制痹筛,在增、刪廓鞠、改時(shí)會(huì)驗(yàn)證多張表中的數(shù)據(jù)關(guān)聯(lián)帚稠,能夠避免不一致的數(shù)據(jù)產(chǎn)生。
2. InnoDB 具體特性
特性 是否支持
B-Tree 索引 支持
server層的備份和事實(shí)恢復(fù) (point-in-time recovery) 支持
數(shù)據(jù)庫(kù)集群 不支持
聚簇索引(clustered index) 支持
壓縮數(shù)據(jù) 支持
數(shù)據(jù)緩存 支持
server層的數(shù)據(jù)加密 支持
外鍵限制 支持
全文索引 (fulltext index) 5.6后支持
空間索引 (Geospatial index) 5.7后支持
Hash索引 不支持
索引緩存 支持
鎖粒度
MVCC(Multi-Version Concurrency Controll)多版本并發(fā)控制 支持
server層的復(fù)制(replication) 支持
存儲(chǔ)限制 64TB
T-Tree 索引 不支持
事務(wù) 支持
數(shù)據(jù)字典的更新統(tǒng)計(jì) 支持

二床佳、表使用 InnoDB 的好處

表使用 InnoDB 存儲(chǔ)引擎的好處有:

  • 不管服務(wù)器由于軟件滋早、硬件問題宕機(jī),無論當(dāng)時(shí) MySQL 上正在執(zhí)行什么任務(wù)砌们,你只需要重新啟動(dòng) MySQL杆麸,InnoDB 的災(zāi)難恢復(fù) (crash-recovery) 能力會(huì)自動(dòng)幫你:把 宕機(jī)時(shí)已提交的變更恢復(fù)回來搁进,把 未提交的變更舍棄掉,繼續(xù)后續(xù)的工作昔头,只需要重新啟動(dòng)就可以了饼问。
  • InnoDB 會(huì)維護(hù)一個(gè)自己的內(nèi)存緩存 buffer pool,把訪問過的數(shù)據(jù)和索引緩存到內(nèi)存中揭斧,而經(jīng)常訪問的數(shù)據(jù)是直接從內(nèi)存中獲取的莱革。這個(gè)內(nèi)存 buffer pool 緩存緩存了很多數(shù)據(jù),進(jìn)一步提升 InnoDB 的處理速度讹开。在專門做數(shù)據(jù)庫(kù)的服務(wù)器上盅视,甚至經(jīng)常會(huì)將80%的內(nèi)存分配給這個(gè) buffer pool
  • 如果你將相關(guān)的數(shù)據(jù)分開存儲(chǔ)到了多張表中旦万,InnoDB 中的外鍵 (foreign key) 限制將使你能保證數(shù)據(jù)的完整性 (integrity)闹击。
    • 更新或刪除主表中的數(shù)據(jù),子表的更新和刪除是由外鍵限制自動(dòng)完成的成艘。
    • 當(dāng)直接插入子表時(shí)赏半,外鍵限制會(huì)自動(dòng)檢查主表的主鍵是否存在,直接剔除不完整的插入淆两。
  • 當(dāng)磁盤除破、內(nèi)存中的數(shù)據(jù)被破壞時(shí),InnoDBchecksum 機(jī)制琼腔,會(huì)提醒你數(shù)據(jù)的不完整性瑰枫。
  • 當(dāng)你在數(shù)據(jù)庫(kù)設(shè)計(jì)時(shí),如果給每張表都設(shè)置了一個(gè)合適的主鍵 (primary keys) 丹莲,那么涉及到這些主鍵 (primary keys) 的操作都會(huì)自動(dòng)優(yōu)化光坝,對(duì)于使用了主鍵 (primary keys)where order by group by join 都將非常快甥材。
  • change buffering 機(jī)制會(huì)自動(dòng)優(yōu)化插入盯另、更新、刪除操作洲赵。InnoDB不僅允許對(duì)同一個(gè)表進(jìn)行并發(fā)讀寫訪問鸳惯,還緩存更改后的數(shù)據(jù)以優(yōu)化磁盤I/O。
  • 性能的提升不僅僅是支持大表的重查詢 (long-running queries)叠萍,當(dāng)頻繁的從一個(gè)表獲取相同數(shù)據(jù)時(shí)芝发,自適應(yīng) hash 索引 (Adaptive Hash Index) 將會(huì)緩存這樣的查詢結(jié)果,使得查詢非晨凉龋快辅鲸,就像使用了 hash 索引的表一樣。
  • 支持多表和索引的壓縮
  • 使得創(chuàng)建腹殿、銷毀索引對(duì)性能和可用性上的影響變得很小
  • 對(duì)于清空一個(gè)單文件表空間 (file-per-table tablespace) 來說独悴,變得更快例书。使得磁盤空間釋放出來給操作系統(tǒng)用,而不是僅僅從 MySQL 的 InnoDB 表空間中釋放出來刻炒,給 InnoDB 表用决采。
  • 使用了動(dòng)態(tài)行結(jié)構(gòu) (dynamic row format),這讓 InnoDB 對(duì) blobtext 字段的存儲(chǔ)和訪問上更高效坟奥。
  • 可以通過查詢 INFORMATION_SCHEMA 表织狐,對(duì) InnoDB 內(nèi)部的工作進(jìn)行監(jiān)控。
  • 可以通過查詢 Performance Schema 表筏勒,對(duì) InnoDB 的性能細(xì)節(jié)進(jìn)行監(jiān)控。
  • 可以自由地在一個(gè)語(yǔ)句中混合 (mix) 使用 InnoDB 和其他存儲(chǔ)引擎旺嬉。例如:可以在一條語(yǔ)句中使用 join 合并 InnoDBmemory 存儲(chǔ)引擎的數(shù)據(jù)管行。
  • InnoDB 在處理大量數(shù)據(jù)的 CPU 運(yùn)算上有很好的性能。
  • 即使在一個(gè)文件最大 2GB 的操作系統(tǒng)上邪媳,InnoDB 的表可以存儲(chǔ)大量數(shù)據(jù)捐顷。

三、InnoDB 表的最佳實(shí)踐

InnoDB 表的最佳實(shí)踐包含:

  • 為每個(gè)存在大量查詢的表指定一個(gè)主鍵 (primary keys)雨效,或者選擇一個(gè)自增類型的字段作為主鍵 (primary keys)迅涮。
  • 基于每個(gè)表的 id 字段使用 join 操作。出于性能考慮徽龟,在 join 的字段上增加外鍵 (foreign key) 限制叮姑,并且將每個(gè)表中的這個(gè)字段設(shè)置為同樣的數(shù)據(jù)類型。增加外鍵 (foreign key) 限制保證了不同表中的關(guān)聯(lián)字段可以使用索引据悔,同時(shí)使得刪除和更新這些字段能影響到所有(有外鍵 (foreign key) 限制的)表传透,還能保證子表和主表的數(shù)據(jù)完整性瞒渠。
  • 關(guān)閉事務(wù)的自動(dòng)提交 (autocommit)玖详。每秒鐘提交數(shù)百個(gè)事務(wù)將限制 InnoDB 的性能抖韩。
  • 將大量的 DML (Data Manipulation Language) 語(yǔ)句傻咖,分組放到多個(gè)事務(wù)中纺棺,使用 start transactioncommit 包起來获黔。雖然你不想太過頻繁的提交事務(wù)拒逮,但你肯定也不想看到硕噩,運(yùn)行了幾個(gè)小時(shí)的 insert 語(yǔ)句骇径,最后沒有提交躯肌。
  • 不要使用 lock table 語(yǔ)句。InnoDB 在不犧牲可用性和高性能的前提下破衔,支持多個(gè)會(huì)話 (session) 同時(shí)對(duì)同一個(gè)表的并發(fā)讀寫羡榴。為了排他性 (exclusive) 地訪問一些行的寫入操作,可以使用 select ... for update 語(yǔ)句运敢,單獨(dú)只鎖定你需要的行校仑。
  • 開啟 innodb_file_per_table 選項(xiàng)或者使用普通表空間 (general tablespace)忠售,使得每張表的數(shù)據(jù)和索引分開存儲(chǔ)在不同的文件中,而不是使用系統(tǒng)表空間 (system tablespace)迄沫。 innodb_file_per_table 默認(rèn)是開啟的稻扬。
  • 評(píng)估是否你的數(shù)據(jù)、訪問方式能從 InnoDB 的表羊瘩、頁(yè) (page) 的壓縮功能中獲益泰佳。InnoDB 在不犧牲讀寫能力的前提下,支持壓縮功能尘吗。
  • 如果在 create table 時(shí)使用 engine=xxx 有問題的話逝她,可以在啟動(dòng) MySQL 服務(wù)時(shí),通過 --sql_mode=NO_ENGINE_SUBSTITUTION 選項(xiàng)禁止創(chuàng)建其他存儲(chǔ)引擎的表睬捶。

四黔宛、確認(rèn) InnoDB 是否是默認(rèn)的存儲(chǔ)引擎

可以通過 show engines; 或者 SELECT * FROM INFORMATION_SCHEMA.ENGINES; 來查看 InnoDB 是否是默認(rèn)的存儲(chǔ)引擎。注意 InnoDB 那行的 default 字樣擒贸。

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)

mysql> select * from INFORMATION_SCHEMA.ENGINES;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| ENGINE             | SUPPORT | COMMENT                                                        | TRANSACTIONS | XA   | SAVEPOINTS |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)

五臀晃、找個(gè)表測(cè)試一下 InnoDB

  • 如果你沒有把 InnoDB 作為默認(rèn)的存儲(chǔ)引擎,可以通過啟動(dòng)參數(shù)中增加 --default-storage-engine=InnoDB 或者在 my.cnf[mysqld] 下增加 default-storage-engine=innodb 的方式介劫,來檢驗(yàn)下你的數(shù)據(jù)服務(wù)徽惋、應(yīng)用是否正常。
  • 如果你的應(yīng)用有依賴其他存儲(chǔ)引擎的某個(gè)特性座韵,將得到一個(gè) add the ENGINE=other_engine_name clause to the CREATE TABLE statement to avoid the error. 的錯(cuò)誤险绘。
  • 如果你想看一下某個(gè)表在 InnoDB 存儲(chǔ)引擎下的具體表,可以通過 ALTER TABLE table_name ENGINE=InnoDB; 的方式修改指定表使用的存儲(chǔ)引擎誉碴。
  • 如果你不想破壞原表隆圆、或者影響正在運(yùn)行的應(yīng)用,可以通過 CREATE TABLE table_xxx_innodb (...) ENGINE=InnoDB AS SELECT * FROM table_xxx; 的方式翔烁,制作一個(gè)備份表渺氧。
  • 當(dāng)你的數(shù)據(jù)服務(wù)是一個(gè)集群時(shí),要特別注意 masterslaves 的版本差異蹬屹。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末侣背,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子慨默,更是在濱河造成了極大的恐慌贩耐,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件厦取,死亡現(xiàn)場(chǎng)離奇詭異潮太,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門铡买,熙熙樓的掌柜王于貴愁眉苦臉地迎上來更鲁,“玉大人,你說我怎么就攤上這事奇钞≡栉” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵景埃,是天一觀的道長(zhǎng)媒至。 經(jīng)常有香客問我,道長(zhǎng)谷徙,這世上最難降的妖魔是什么拒啰? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮完慧,結(jié)果婚禮上谋旦,老公的妹妹穿的比我還像新娘。我一直安慰自己骗随,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布赴叹。 她就那樣靜靜地躺著鸿染,像睡著了一般。 火紅的嫁衣襯著肌膚如雪乞巧。 梳的紋絲不亂的頭發(fā)上涨椒,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音绽媒,去河邊找鬼蚕冬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛是辕,可吹牛的內(nèi)容都是我干的囤热。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼获三,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼旁蔼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起疙教,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤棺聊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后贞谓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體限佩,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了祟同。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片作喘。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖耐亏,靈堂內(nèi)的尸體忽然破棺而出徊都,到底是詐尸還是另有隱情,我是刑警寧澤广辰,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布暇矫,位于F島的核電站,受9級(jí)特大地震影響择吊,放射性物質(zhì)發(fā)生泄漏李根。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一几睛、第九天 我趴在偏房一處隱蔽的房頂上張望房轿。 院中可真熱鬧,春花似錦所森、人聲如沸囱持。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纷妆。三九已至,卻和暖如春晴弃,著一層夾襖步出監(jiān)牢的瞬間掩幢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工上鞠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留际邻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓芍阎,卻偏偏與公主長(zhǎng)得像世曾,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谴咸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354