把總結寫開頭:
1)像InnoDB和MyISAM這樣的存儲引擎都是把數據存儲在文件系統上的。
MySQL服務器程序在啟動的時候會到數據目錄中加載數據,運行過程中產生的數據也會存儲到數據目錄中。系統變量datadir表明了數據目錄的路徑。
每個數據庫都對應着數據目錄的一個子目錄,該子目錄包含一個db.opt文件,這個文件包含數據庫的一些屬性,比如該數據庫的字符集和比較規則等。
對於InnoDB來講:
1. 如果使用系統表空間存儲表中的內容,那么只會在該表所在的數據庫對應的子目錄創建一個“表名.frm”,表中的數據就會存儲在系統表空間對應的文件夾中。
2. 如果使用獨立表空間存儲表中的數據,那么會生成一個“表名.ibd”文件和一個“表名.frm”的文件,表中的數據存在表名.ibd文件中。
對於MyISAM:
1. 表名.frm :表示表的結構文件。
2. 表名.MYD: 表示表的數據文件。
3. 表名.MYI: 表示表的索引文件。
2)數據目錄除了存儲用戶數據外,還會存儲一些額外的文件包括:服務進程文件,服務日志文件,SSL和RSA證書與密鑰文件。
3)特定的文件系統會對MySQL服務器程序的運行產生一些影響,比如:
1. 數據庫名稱和表名稱不得超過文件系統所允許的最大長度。
2. 特殊字符的問題。
3. 文件長度受文件系統最大長度的限制。
一、數據庫和文件系統的關系
-
InnoDB 、 MyISAM 這樣的存儲引擎都是把表存儲在文件系統上的。當我們想讀取數據的時候,這些存儲引擎會從文件系統中把數據讀出來返回給我們,當我們想寫入數據的時候,這些存儲引擎會把這些數據又寫回文件系統。
二、MySQL數據目錄
- MySQL服務器程序在啟動時會到文件系統的某個目錄下加載一些文件,之后在運行過程中產生的數據也都會存儲到這個目錄下的某些文件中,這個目錄就稱為
數據目錄
。
1、數據目錄和安裝目錄的區別
-
MySQL
的安裝目錄(在安裝MySQL
的時候我們可以自己指定),我們重點強調過這個安裝目錄
下非常重要的bin
目錄,它里邊存儲了許多關於控制客戶端程序和服務器程序的命令(許多可執行文件,比如mysql
,mysqld
,mysqld_safe
等等等等好幾十個)。 -
而
數據目錄
是用來存儲MySQL
在運行過程中產生的數據,一定要和本章要討論的安裝目錄
區別開!一定要區分開!一定要區分開!一定要區分開!
2、如何確定MySQL中的數據目錄
- 那說了半天,到底
MySQL
把數據都存到哪個路徑下呢?其實數據目錄
對應着一個系統變量datadir
,我們在使用客戶端與服務器建立連接之后查看這個系統變量的值就可以了:
mysql> SHOW VARIABLES LIKE 'datadir'; +---------------+-----------------------+ | Variable_name | Value | +---------------+-----------------------+ | datadir | /usr/local/var/mysql/ | +---------------+-----------------------+ 1 row in set (0.00 sec)
- 從結果中可以看出,在我的計算機上
MySQL
的數據目錄就是/usr/local/var/mysql/
三、數據目錄的結構
MySQL
在運行過程中都會產生哪些數據呢?當然會包含我們創建的數據庫、表、視圖和觸發器吧啦吧啦的用戶數據,除了這些用戶數據,為了程序更好的運行,MySQL
也會創建一些其他的額外數據,我們接下來細細的品味一下這個數據目錄
下的內容。
1、數據庫在文件系統中的表示
-
每當我們使用
CREATE DATABASE 數據庫名
語句創建一個數據庫的時候,在文件系統上實際發生了什么呢?其實很簡單,每個數據庫都對應數據目錄下的一個子目錄,或者說對應一個文件夾,我們每當我們新建一個數據庫時,MySQL
會幫我們做這兩件事兒:-
在
數據目錄
下創建一個和數據庫名同名的子目錄(或者說是文件夾)。 -
在該與數據庫名同名的子目錄下創建一個名為
db.opt
的文件,這個文件中包含了該數據庫的各種屬性,比方說該數據庫的字符集和比較規則是個啥。
-
-
比方說我們查看一下在我的計算機上當前有哪些數據庫:
mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | charset_demo_db | | dahaizi | | mysql | | performance_schema | | sys | | xiaohaizi | +--------------------+ 7 rows in set (0.00 sec)
可以看到在我的計算機上當前有7個數據庫,其中charset_demo_db
、dahaizi
和xiaohaizi
數據庫是我們自定義的,其余4個數據庫是屬於MySQL自帶的系統數據庫。我們再看一下我的計算機上的數據目錄
下的內容:
.
├── auto.cnf
├── ca-key.pem ├── ca.pem ├── charset_demo_db ├── client-cert.pem ├── client-key.pem ├── dahaizi ├── ib_buffer_pool ├── ib_logfile0 ├── ib_logfile1 ├── ibdata1 ├── ibtmp1 ├── mysql ├── performance_schema ├── private_key.pem ├── public_key.pem ├── server-cert.pem ├── server-key.pem ├── sys ├── xiaohaizideMacBook-Pro.local.err ├── xiaohaizideMacBook-Pro.local.pid └── xiaohaizi 6 directories, 16 files
當然這個數據目錄下的文件和子目錄比較多哈,但是如果仔細看的話,除了information_schema
這個系統數據庫外,其他的數據庫在數據目錄
下都有對應的子目錄。這個information_schema
比較特殊。
2、表在文件系統中的表示
-
我們的數據其實都是以記錄的形式插入到表中的,每個表的信息其實可以分為兩種:
- 表結構的定義
- 表中的數據
-
表結構
就是該表的名稱是啥,表里邊有多少列,每個列的數據類型是啥,有啥約束條件和索引,用的是啥字符集和比較規則吧啦吧啦的各種信息,這些信息都體現在了我們的建表語句中了。為了保存這些信息,InnoDB
和MyISAM
這兩種存儲引擎都在數據目錄
下對應的數據庫子目錄下創建了一個專門用於描述表結構的文件,文件名是這樣:
表名.frm
- 比方說我們在
dahaizi
數據庫下創建一個名為test
的表:
mysql> USE dahaizi; Database changed mysql> CREATE TABLE test ( -> c1 INT -> ); Query OK, 0 rows affected (0.03 sec)
- 那在數據庫
dahaizi
對應的子目錄下就會創建一個名為test.frm
的用於描述表結構的文件。值得注意的是,這個后綴名為.frm是以二進制格式存儲的
(1)InnoDB是如何存儲表數據的
前邊重點嘮叨過InnoDB
的一些實現原理,到現在為止我們應該熟悉下邊這些東東:
-
InnoDB
其實是使用頁
為基本單位來管理存儲空間的,默認的頁
大小為16KB
。 -
對於
InnoDB
存儲引擎來說,每個索引都對應着一棵B+
樹,該B+
樹的每個節點都是一個數據頁,數據頁之間不必要是物理連續的,因為數據頁之間有雙向鏈表
來維護着這些頁的順序。 -
InnoDB
的聚簇索引的葉子節點存儲了完整的用戶記錄,也就是所謂的索引即數據,數據即索引。 -
為了更好的管理這些頁,設計
InnoDB
的大叔們提出了一個表空間
或者文件空間
(英文名:table space
或者file space
)的概念,這個表空間是一個抽象的概念,它可以對應文件系統上一個或多個真實文件(不同表空間對應的文件數量可能不同)。每一個表空間
可以被划分為很多很多很多個頁
,我們的表數據就存放在某個表空間
下的某些頁里。設計InnoDB
的大叔將表空間划分為幾種不同的類型,我們一個一個看一下。
(2)系統表空間(system tablespace)
-
這個所謂的
系統表空間
可以對應文件系統上一個或多個實際的文件,默認情況下,InnoDB
會在數據目錄
下創建一個名為ibdata1
(在你的數據目錄下找找看有木有)、大小為12M
的文件,這個文件就是對應的系統表空間
在文件系統上的表示。怎么才12M
?這么點兒還沒插多少數據就用完了,哈哈,那是因為這個文件是所謂的自擴展文件
,也就是當不夠用的時候它會自己增加文件大小~ -
當然,如果你想讓系統表空間對應文件系統上多個實際文件,或者僅僅覺得原來的
ibdata1
這個文件名難聽,那可以在MySQL
啟動時配置對應的文件路徑以及它們的大小,比如我們這樣修改一下配置文件:
[server]
innodb_data_file_path=data1:512M;data2:512M:autoextend
- 這樣在
MySQL
啟動之后就會創建這兩個512M大小的文件作為系統表空間
,其中的autoextend
表明這兩個文件如果不夠用會自動擴展data2
文件的大小。
在一個MySQL服務器中,系統表空間只有一份
(3)獨立表空間(file-per-table tablespace)
- 在MySQL5.6.6以及之后的版本中,
InnoDB
並不會默認的把各個表的數據存儲到系統表空間中,而是為每一個表建立一個獨立表空間,也就是說我們創建了多少個表,就有多少個獨立表空間。使用獨立表空間
來存儲表數據的話,會在該表所屬數據庫對應的子目錄下創建一個表示該獨立表空間
的文件,文件名和表名相同,只不過添加了一個.ibd
的擴展名而已,所以完整的文件名稱長這樣:
表名.ibd
- 比方說假如我們使用了
獨立表空間
去存儲xiaohaizi
數據庫下的test
表的話,那么在該表所在數據庫對應的xiaohaizi
目錄下會為test
表創建這兩個文件:
test.frm
test.ibd
- 其中
test.ibd
文件就用來存儲test
表中的數據和索引。當然我們也可以自己指定使用系統表空間
還是獨立表空間
來存儲數據,這個功能由啟動參數innodb_file_per_table
控制,比如說我們想刻意將表數據都存儲到系統表空間
時,可以在啟動MySQL
服務器的時候這樣配置:
[server]
innodb_file_per_table=0
當innodb_file_per_table
的值為0
時,代表使用系統表空間;當innodb_file_per_table
的值為1
時,代表使用獨立表空間。不過innodb_file_per_table
參數只對新建的表起作用,對於已經分配了表空間的表並不起作用。如果我們想把已經存在系統表空間中的表轉移到獨立表空間,可以使用下邊的語法:
ALTER TABLE 表名 TABLESPACE [=] innodb_file_per_table;
或者把已經存在獨立表空間的表轉移到系統表空間,可以使用下邊的語法:
ALTER TABLE 表名 TABLESPACE [=] innodb_system;
其中中括號擴起來的=
可有可無,比方說我們想把test
表從獨立表空間移動到系統表空間,可以這么寫:
ALTER TABLE test TABLESPACE innodb_system;
(4)其他類型的表空間
隨着MySQL的發展,除了上述兩種老牌表空間之外,現在還新提出了一些不同類型的表空間,比如通用表空間(general tablespace)、undo表空間(undo tablespace)、臨時表空間(temporary tablespace)吧啦吧啦的,具體情況我們就不細嘮叨了,等用到的時候再提。
3、MySQL系統數據庫簡介
1) mysql : 這個數據庫存儲了MySQL的賬戶信息和權限信息,一些存儲過程和事件的定義信息,一些運行過程中產生的日志信息,一些幫助信息以及時區信息。
2) information_schema: 這個數據庫保存着MySQL服務器維護的所有數據庫的信息,比如有哪些表,哪些視圖,哪些觸發器,哪些列,哪些索引等。這些信息並不是用戶數據,而是一些描述性信息,有時候也成為元數據。
3) performance_schema: 這個數據庫主要保存MySQL服務器運行過程中的一些狀態信息,算是對MySQL服務器的一個性能監控。它包含的信息有統計最近執行的語句,在執行過程每個階段都花費了多少時間,內存的使用情況等。
4) sys: 這個數據庫主要通過視圖形式把information_schema 和 performance_schema結合起來,讓開發人員更方便的了解MySQL服務器的性能信息。