在上一篇里面,bingxi和alex思考了information_schema,這個一直在innodb外圍打轉。沒有進入到innodb的內部。在后續的文章中,以innodb的為主,逐個思考。Bingxi和alex今天了解了fil文件管理。
對應的文件為:
D:/mysql-5.1.7-beta/storage/innobase/fil/fil0fil.c
D:/mysql-5.1.7-beta/storage/innobase/include/fil0fil.h
## 1)所謂的tablespace
Bingxi:“alex,配置項有一個選項innodb_file_per_table,也就是每個表有一個自己的tablespace。
14.2.3.1. Using Per-Table Tablespaces
You can store each InnoDB table and its indexes in its own file. This feature is called “multiple tablespaces” because in effect each table has its own tablespace.
”
Alex:“是的,bingxi。不過tablespace這個概念我們借鑒了oracle中的命名:表空間。在oracle中,tablespace表示表的集合,也就是很多個表放到同一個邏輯整體里面。”
Bingxi:“是的,相比myisam,每個myisam表對應三個文件。而innodb可以將很多表放到一個文件或者多個文件里面,這個叫共享表空間。另外,如果innodb_file_per_table加到配置文件,則每個新建的innodb表則使用獨立表空間。”
Alex:“bingxi,那什么叫獨立表空間呢?我們需要來debug一下代碼。假設我們使用系統默認的參數啟動,則會有兩個tablespace,第一個tablespace包括一個文件ibdata1,這個也可以稱為系統表空間,另外一個space包括兩個日志文件。”
Bingxi:“是的,我們參考了oracle的系統表空間就知道系統表空間里面會存放很多字典信息。這里我們先不說那么遠,先說下如果我們需要將系統表空間的文件數量增加,應該怎么填寫?因為我們是debug環境下,我們在D:/mysql-5.1.7-beta目錄下創建一個my.ini,在其中寫入兩行參數:
[mysqld]
[innodb_data_file_path]= ibdata1:10M;ibdata2:20M:autoextend
這表示系統表空間里面就會有兩個文件,其中第一個文件ibdata1是10M,第二個文件大小是是20M,并且可以進行自動擴展。
”
Alex:“好吧,我們現在先配置下文件,然后看看系統內部是如何管理這些文件的。先看看文件系統的定義。
~~~
//文件系統管理結構
typedef??? struct fil_system_struct fil_system_t;
struct fil_system_struct {
? ……
? //下面兩個表空間用于快速查找space,fil_system_t結構用于整個fil的管理。
? //注意:這里的最低粒度是文件
?????? hash_table_t*? spaces;?????????? ? //根據space id進行hash的space
?????? hash_table_t*? name_hash;? //根據space name進行hahs的space
?????? ……
??????
?????? //file space的鏈表,比如這里有兩個space,一個是系統表空間,一個是log space
?????? UT_LIST_BASE_NODE_T(fil_space_t) space_list;
};?
?從上面的結構中,我們可以看到fil_system_t與fil_space_t是一對多的關系。
/* Tablespace or log data space: let us call them by a common name space */
struct fil_space_struct {
?????? char*???????????? name;????? //space name = 該space的第一個文件名
?????? ulint??????? id;??? ?? //space id
?????? ……
??? //該space包含的文件結點鏈表
?????? UT_LIST_BASE_NODE_T(fil_node_t) chain;? //文件鏈表
? ……??????????
?????? //指向下一個space
?????? UT_LIST_NODE_T(fil_space_t) space_list;
?????? ……
};
~~~
? 從這個結構中我們也可以看出,fil_space_struct與fil_node_t也是一對多的關系,也就是一個space下面可以包含多個文件。從我們的my.ini中可以得知我們的系統表空間是對應兩個文件:ibdata1、ibdata2。我們來具體看看fil_node_t的定義。
~~~
/* File node of a tablespace or the log data space */
struct fil_node_struct {
?????? fil_space_t*??? space;???? //所屬的space
?????? char*???????????? name;????? ? //文件路徑
?????? ibool????????????? open;????? ? //文件是否打開
?????? os_file_t? handle;? //文件句柄
?????? ulint??????? size; ? //文件大小
? ……
?????? UT_LIST_NODE_T(fil_node_t) chain;? //文件結點鏈表
?????? ……
};
~~~
啟動后的圖如下圖1
//file space的鏈表,比如這里有兩個space,一個是系統表空間,一個是log space
?????? UT_LIST_BASE_NODE_T(fil_space_t) space_list;

”
Bingxi:“是的,我們看下系統表空間這個space里的size這個字段,里面的size為1920,等于對應的兩個文件大小的相加,640+1280。這個640是怎么計算的呢,文件頁的大小為16k,而ibdata1的大小為10M,因此對應的頁數為640頁。因此這里的值為640。同樣的ibdata2的頁數為20M/16k=1280。”
Alex:“好的,我們可以看到這里僅僅是將結點生成了,還需要將日志文件以及系統表空間的的文件打開,保持打開直到數據庫shut down。
~~~
int
innobase_start_or_create_for_mysql(void)
{
?????? ……
??? //打開所有的日志文件以及系統表空間中的文件,保持打開直到數據庫shut down
?????? fil_open_log_and_system_tablespace_files();
? ……
}
~~~
在開始進一步之前,我們先看下獨立表空間。目前正在使用的是系統表空間,執行語句,往系統表空間里面插入數據。執行后將數據庫shut down。然后往my.ini里面增加一行配置用于使用獨立表空間。
[mysqld]
innodb_data_file_path = ibdata1:10M;ibdata2:20M:autoextend
innodb_file_per_table = 1
? 重啟后執行如下語句
mysql> use test;
Database changed
mysql> create table t2(id int) engine=innodb;
Query OK, 0 rows affected (0.02 sec)
執行語句后,我們可以發現test生成了兩個文件:t2.frm以及t2.ibd。同時,我們測試下,能不能在配置為獨立表空間的情況下,執行查詢語句,發現還是可以使用共享表空間(和系統表空間一個意思)的數據。
mysql> select * from t1;
+------+-------+
| id?? | name? |
+------+-------+
|??? 1 | name1 |
|??? 2 | name2 |
+------+-------+
2 rows in set (0.02 sec)
同理,我們重新修改my.ini,去掉獨立表空間的配置項,也能使用之前創建的t2表。然后看下文件系統的space_list的數量為3了。也就是t2表對應的表空間。
?

”
Bingxi“我們先說到這里吧,內容還是很多的,建議將fil0fil.c中每個函數設置一個斷點,然后通過語句調試的方式來掌握,比如往t1里面插數據,直到30M數據不夠,要進行文件的擴展,然后跟蹤進去看下如何進行文件的擴展等等。”
Alex:“是的,我們今天聊了表空間管理,那么后續就可以討論系統表空間內是如何組織數據的了。”
Bingxi:“alex,先把基礎的講下,比如今天里面包含的兩個常用結構:hash_table_t、UT_LIST_NODE_T。”
Alex:“嗯,可以的,我們下次聊這個。”