Ⅰ、InnoDB發(fā)展史
時間 | 事件 | 備注 |
---|---|---|
1995 | 由Heikki Tuuri創(chuàng)建Innobase Oy公司,開發(fā)InnoDB存儲引擎 | Innobase開始做的是數(shù)據(jù)庫计维,希望賣掉該公司 |
1996 | MySQL 1.0 發(fā)布 | |
2000 | MySQL3.23版本發(fā)布 | |
2001 | InnoDB存儲引擎集成到MySQL數(shù)據(jù)庫 | 以插件方式集成 |
2006 | Innobase被Oracle公司收購(InnoDB作為開源產(chǎn)品,性能和功能很強大) | InnoDB在被收購后的曾沈,MySQL中的InnoDB版本沒有改變 |
2010 | MySQL5.5版本InnoDB存儲引擎稱為默認(rèn)存儲引擎 | MySQL被Sun收購,Sun被Oracle收購迷扇,使得MySQL和InnoDB重新在一起配合開發(fā) |
至今 | 其他存儲引擎已經(jīng)不再得到Oracle官方的后續(xù)開發(fā) |
Ⅱ、InnoDB重要特性一覽
- Fully ACID(InnoDB默認(rèn)的Repeat Read隔離級別就支持)
- Row-level Locking(支持行鎖)
- Multi-version concurrency control(MVCC)(支持多版本并發(fā)控制)
- Foreign key support(支持外鍵)
- Automatic deadlock detection(死鎖自動檢測)
- High performance爽哎、High scalability蜓席、High availability(高性能,高擴(kuò)展课锌,高可用)
Ⅲ厨内、物理存儲結(jié)構(gòu)
3.1 主要組成部分
表空間文件:
- 獨立表空間
- 共享表空間
- undo表空間(MySQL5.6開始)
重做日志文件:
- 物理邏輯日志
- 沒有Oracle的歸檔重做日志
3.2 細(xì)說表空間文件
表空間的概念:
- 表空間是一個邏輯存儲的概念
- 表空間可以由多個文件組成
- 支持裸設(shè)備(可以直接使用O_DIRECT 方式繞過緩存,直接寫入磁盤)
表空間的分類:
①共享表空間(最早只有這個)
- 存儲元數(shù)據(jù)信息
- 存儲Change Buffer信息
- 存儲Undo信息
- MySQL4.0之前所有數(shù)據(jù)都是存儲在共享表空間中
②獨立表空間
- MySQL4.0開始渺贤,支持每張表對應(yīng)一個獨立表空間(ibd文件)
- innodb-file-per-table=1(默認(rèn)為1雏胃,這個參數(shù)關(guān)掉創(chuàng)建表,會發(fā)現(xiàn)對應(yīng)的庫下面沒有該表的idb文件)
- 分區(qū)表可以對應(yīng)多個ibd文件
③undo表空間
- MySQL5.6版本支持獨立的Undo表空間,默認(rèn)是0志鞍,即undo記錄在共享表空間中
- innodb_undo_tablespaces(該值8.0開始將會被剔除瞭亮,不可修改,默認(rèn)寫死固棚,為2)
④臨時表空間
- MySQL5.7增加了臨時表空間(ibtmp1)
- innodb_temp_data_file_path
3.3 看下數(shù)據(jù)目錄
[root@VM_0_5_centos data3306]# ll ib*
-rw-r----- 1 mysql mysql 16285 Feb 4 18:15 ib_buffer_pool
-rw-r----- 1 mysql mysql 79691776 Feb 24 10:53 ibdata1 #共享表空間
-rw-r----- 1 mysql mysql 50331648 Feb 24 10:53 ib_logfile0 #重做日志
-rw-r----- 1 mysql mysql 50331648 Feb 4 15:06 ib_logfile1
-rw-r----- 1 mysql mysql 12582912 Feb 24 10:14 ibtmp1 #臨時表空間
兩個ib_logfile是循環(huán)交替寫入的统翩,SSD下盡可能設(shè)大,單個文件4G/8G此洲,設(shè)置太小可能會導(dǎo)致臟頁刷新時hang住
MySQL中現(xiàn)在只有這兩個文件不會歸檔唆缴,最老的3.23版本支持歸檔,因為MySQL有二進(jìn)制日志所以把這個功能閹割了
[root@VM_0_5_centos data3306]# cd test
[root@VM_0_5_centos test]# ll
total 228
-rw-r----- 1 mysql mysql 65 Feb 4 13:21 db.opt #記錄默認(rèn)字符集和字符集排序規(guī)則
-rw-r----- 1 mysql mysql 8554 Feb 1 15:45 abc.frm #表結(jié)構(gòu)文件
-rw-r----- 1 mysql mysql 98304 Feb 24 10:53 abc.ibd #獨立表空間
就性能而言黍翎,獨立和共享速度是一樣的面徽,基本上區(qū)別
雖然ibadta1是一個文件,但是在底層申請也是1兆1兆地申請的空間匣掸,是連續(xù)的(兩種都是以區(qū)的方式來管理)趟紊,在磁盤上的表現(xiàn)是一樣的,1M的數(shù)據(jù)基本上可以認(rèn)為是連續(xù)的
tips:
sysbench去測8個文件開16個線程和測1個文件開128個線程碰酝,測出來iops是一樣的霎匈,因為它的分配和管理機制都是一樣的
那為什么MySQL4.0版本開始引入了獨立表空間呢?
主要是為了管理方便送爸,表現(xiàn)為:
- 看上去清晰
- 刪除文件非常簡單铛嘱,drop完空間可釋放,對于ibdata1來說袭厂,一個文件墨吓,只能增不能減,刪除一張表只是把這張表對應(yīng)的空間標(biāo)為可用纹磺,但是空間并不能回收
刪除.ibd文件是不行的帖烘,因為對應(yīng)的innodb元數(shù)據(jù)表里面的數(shù)據(jù)沒有刪
.ibd和.ibdata1文件壞了修復(fù)的話收費是按行數(shù)來算的很貴的哦,相對而言ibdata1文件修復(fù)難度更大
切記:不要在數(shù)據(jù)目錄下刪除任何文件
3.4 小常識
單個ibd文件直接拷貝到新的數(shù)據(jù)庫中無法直接恢復(fù):
- 原因一:元數(shù)據(jù)信息還是在ibdata1中
- 原因二:部分索引文件存在于Change Buffer中橄杨,目前還是存放于ibdata1文件中
查看表空間的元數(shù)據(jù)信息
select * from information_schema.innodb_sys_tablespaces;
Ⅳ秘症、邏輯存儲結(jié)構(gòu)
4.1 從上到下的結(jié)構(gòu)
表空間 |
---|
內(nèi)部有多個段對象(Segment)組成 |
每個段(Segment)由區(qū)(Extent)組成 |
每個區(qū)(Extent)由頁(Page)組成 |
每個頁里面保存數(shù)據(jù)(或者叫記錄Row) |
段:
段對用戶來說是透明的照卦,也是一個邏輯的概念,用來組織管理區(qū)
在MySQL系統(tǒng)表中是看不到段這個元數(shù)據(jù)的乡摹,但是邏輯上的確存在(重點理解區(qū)和頁)
區(qū):
區(qū)包含頁
區(qū)是最小的空間申請單位役耕,表空間文件要擴(kuò)展是以區(qū)的單位來擴(kuò)展
區(qū)的大小固定為1M,這1M在物理上是連續(xù)的聪廉,但1M和1M之間不保證連續(xù)
page_size=16K 就是1M * 1024 / 16 = 64個頁
16k 64個頁
8k 128個頁
4k 256個頁
通常一次申請4個區(qū)大小瞬痘,1兆1兆地申請,特殊情況會申請5個區(qū)锄列,很少發(fā)生這種情況
頁 :
等價于ORACLE中的塊 ,最小的I/O操作單位
tips:
data的最小單位不是頁图云,而是頁中的記錄(row)
普通用戶表中MySQL默認(rèn)的每個頁為16K
- 從MySQL 5.6開始使用 innodb_page_size可以控制頁大小
- 一旦數(shù)據(jù)庫通過innodb_page_size創(chuàng)建完成,則后續(xù)無法更改
- innodb_page_size 是針對普通表的,壓縮表不受其限制
4.2 來來來邻邮,吹兩手
從5.6開始可以調(diào)整大小竣况,但只能設(shè)置4k和8k,從5.7開始還可以設(shè)置32k筒严,64k丹泉,如果設(shè)置為32k或者64k那區(qū)的大小就變?yōu)?M和4M
什么淘寶標(biāo)準(zhǔn)MySQL配置參數(shù)把這個大小設(shè)置為4k,完全扯淡鸭蛙,就算在ssd下4k可能也不會比16k好摹恨,另外設(shè)置為4k,io操作會變多娶视,不要迷信晒哄,現(xiàn)在的表偏向于寬表(很多列組成,單行記錄比較大),一行超過1k甚至4k以上肪获,這時候這個頁大小設(shè)為4寝凌,性能會很差。
設(shè)置小了孝赫,B+ tree高度變高较木,io變多,性能變差;如果是寬列青柄,4k的頁會導(dǎo)致行外存伐债,效率變差
目前為止,大家都用的SSD致开,列比較寬峰锁,內(nèi)存也比較大,就保留16k或者嘗試一下32k(一些單列特別大的場景喇喉,大頁性能有優(yōu)勢)
tips:
MySQL頁大小和ORACLE頁大小不同的是祖今,MySQL頁大小是全局的,一旦初始化好拣技,就不可再修改千诬,不像ORACLE可以設(shè)置每張表的頁大小
Ⅴ、MySQL中如何定位到一個頁
SpaceID
- 每個表空間都對應(yīng)一個SpaceID膏斤,而表空間又對應(yīng)一個ibd文件徐绑,那么一個ibd文件也對應(yīng)一個SpaceID
- ibdata1對應(yīng)的SpaceID為0,每創(chuàng)建一個表空間(ibd文件)莫辨,SpaceID自增長(全局)
PageNumber
- 在一個表空間中傲茄,第幾個16K的頁(假設(shè) innodb_page_size = 16K)即為PageNumber
+--------------------+--------------+-------------+--------------+
SpaceID | 0 | 1 | | N | # 全局遞增
+----------------------------------------------------------------+
| | || || |
ibd File | ibdata1 | table1.ibd || ...... || tableX.ibd +------+
| | || || | |
+--------+-----------+-------+-----------------------------------+ |
| | |
| | |
| +--------------------------------------+ |
| | |
| | |
+--------v---+------------+--------------------------------------+ | |
| | | || || | | |
| 16K | 16K | 16K || ...... || 16K | | |
| | | || || | | |
+----------------------------------------------------------------+ | |
Page Number| 0 | 1 | 2 | | M | | |
+------------+------------+-------------+------------+-----------+ | | | | | |
+----------------------------------------------------------+ |
| |
| |
| |
| |
+--------v---+------------+--------------------------------------+ |
| | | || || | |
| 16K | 16K | 16K || ...... || 16K | |
| | | || || | |
+----------------------------------------------------------------+ |
Page Number| 0 | 1 | 2 | | M | |
+------------+------------+-------------+------------+-----------+ | |
|
+--------------------------------------------------------------+
|
|
|
+--------v---+------------+--------------------------------------+
| | | || || |
| 16K | 16K | 16K || ...... || 16K |
| | | || || |
+----------------------------------------------------------------+
Page Number| 0 | 1 | 2 | | M |
+------------+------------+-------------+------------+-----------+
# 每個表空間中,都是從0開始遞增沮榜,且僅僅是表空間內(nèi)唯一
- 每次讀取Page時盘榨,都是通過SpaceID和PageNumber進(jìn)行讀取
- 可以簡單理解為從表空間的開頭讀多少個PageNumber * PageSize的字節(jié)(偏移)
- 想成數(shù)組,數(shù)組的名字就是SpaceID蟆融,數(shù)組的下標(biāo)就是PageNumber
- 在一個SpaceID(ibd文件)中草巡,PageNumber是唯一且自增的
- 刪除表的時候,SpaceID不會回收 型酥,SpaceID是全局自增長的
tips:
這里的區(qū)(extent)的概念已經(jīng)弱化
在這個例子中山憨,第一個區(qū)的PageNumber是(0到63)且這64個頁在物理上是連續(xù)的;第二個區(qū)的PageNumber是(64到127) 且這64個頁在物理上也是連的
但是(0到63)和(64到127)之間在物理上則不一定是連續(xù)的弥喉,因為區(qū)和區(qū)之間在物理上不一定是連續(xù)的
隨便看看
(root@localhost) [information_schema]> select space, name from information_schema.innodb_sys_tablespaces order by space limit 5;
+-------+---------------------+
| space | name |
+-------+---------------------+
| 2 | mysql/plugin |
| 3 | mysql/servers |
| 4 | mysql/help_topic |
| 5 | mysql/help_category |
| 6 | mysql/help_relation |
+-------+---------------------+
5 rows in set (0.00 sec)
(root@localhost) [information_schema]> select name, space, table_id from information_schema.innodb_sys_tables where space=0;
+------------------+-------+----------+
| name | space | table_id |
+------------------+-------+----------+
| SYS_DATAFILES | 0 | 14 |
| SYS_FOREIGN | 0 | 11 |
| SYS_FOREIGN_COLS | 0 | 12 |
| SYS_TABLESPACES | 0 | 13 |
| SYS_VIRTUAL | 0 | 15 |
+------------------+-------+----------+
5 rows in set (0.00 sec)
(root@localhost) [information_schema]> select name, space, table_id from information_schema.innodb_sys_tables where space<>0 order by space limit 5;
+---------------------+-------+----------+
| name | space | table_id |
+---------------------+-------+----------+
| mysql/plugin | 2 | 16 |
| mysql/servers | 3 | 17 |
| mysql/help_topic | 4 | 35 |
| mysql/help_category | 5 | 36 |
| mysql/help_relation | 6 | 38 |
+---------------------+-------+----------+
5 rows in set (0.00 sec)
- 獨立表空間的table_id和SpaceID一一對應(yīng)
- 共享表空間是多個table_id對應(yīng)一個SpaceID
- SpaceID為0的是ibdata1郁竟,1這個位置沒有,空的