把總結寫開頭:
明天再寫吧,上床睡覺。
一、資料庫和檔案系統的關系
innodb 、 myisam 這樣的存儲引擎都是把表存儲在檔案系統上的。當我們想讀取資料的時候,這些存儲引擎會從檔案系統中把資料讀出來傳回給我們,當我們想寫入資料的時候,這些存儲引擎會把這些資料又寫回檔案系統。
二、mysql資料目錄
mysql伺服器程式在啟動時會到檔案系統的某個目錄下加載一些檔案,之後在運作過程中産生的資料也都會存儲到這個目錄下的某些檔案中,這個目錄就稱為<code>資料目錄</code>。
<code>mysql</code>的安裝目錄(在安裝<code>mysql</code>的時候我們可以自己指定),我們重點強調過這個<code>安裝目錄</code>下非常重要的<code>bin</code>目錄,它裡邊存儲了許多關于控制用戶端程式和伺服器程式的指令(許多可執行檔案,比如<code>mysql</code>,<code>mysqld</code>,<code>mysqld_safe</code>等等等等好幾十個)。
而<code>資料目錄</code>是用來存儲<code>mysql</code>在運作過程中産生的資料,一定要和本章要讨論的<code>安裝目錄</code>差別開!一定要區分開!一定要區分開!一定要區分開!
那說了半天,到底<code>mysql</code>把資料都存到哪個路徑下呢?其實<code>資料目錄</code>對應着一個系統變量<code>datadir</code>,我們在使用用戶端與伺服器建立連接配接之後檢視這個系統變量的值就可以了:
從結果中可以看出,在我的計算機上<code>mysql</code>的資料目錄就是<code>/usr/local/var/mysql/</code>
三、資料目錄的結構
<code>mysql</code>在運作過程中都會産生哪些資料呢?當然會包含我們建立的資料庫、表、視圖和觸發器吧啦吧啦的使用者資料,除了這些使用者資料,為了程式更好的運作,<code>mysql</code>也會建立一些其他的額外資料,我們接下來細細的品味一下這個<code>資料目錄</code>下的内容。
每當我們使用<code>create database 資料庫名</code>語句建立一個資料庫的時候,在檔案系統上實際發生了什麼呢?其實很簡單,每個資料庫都對應資料目錄下的一個子目錄,或者說對應一個檔案夾,我們每當我們建立一個資料庫時,<code>mysql</code>會幫我們做這兩件事兒:
在<code>資料目錄</code>下建立一個和資料庫名同名的子目錄(或者說是檔案夾)。
在該與資料庫名同名的子目錄下建立一個名為<code>db.opt</code>的檔案,這個檔案中包含了該資料庫的各種屬性,比方說該資料庫的字元集和比較規則是個啥。
比方說我們檢視一下在我的計算機上目前有哪些資料庫:
可以看到在我的計算機上目前有7個資料庫,其中<code>charset_demo_db</code>、<code>dahaizi</code>和<code>xiaohaizi</code>資料庫是我們自定義的,其餘4個資料庫是屬于mysql自帶的系統資料庫。我們再看一下我的計算機上的<code>資料目錄</code>下的内容:
當然這個資料目錄下的檔案和子目錄比較多哈,但是如果仔細看的話,除了<code>information_schema</code>這個系統資料庫外,其他的資料庫在<code>資料目錄</code>下都有對應的子目錄。這個<code>information_schema</code>比較特殊。
我們的資料其實都是以記錄的形式插入到表中的,每個表的資訊其實可以分為兩種:
表結構的定義
表中的資料
<code>表結構</code>就是該表的名稱是啥,表裡邊有多少列,每個列的資料類型是啥,有啥限制條件和索引,用的是啥字元集和比較規則吧啦吧啦的各種資訊,這些資訊都展現在了我們的建表語句中了。為了儲存這些資訊,<code>innodb</code>和<code>myisam</code>這兩種存儲引擎都在<code>資料目錄</code>下對應的資料庫子目錄下建立了一個專門用于描述表結構的檔案,檔案名是這樣:
比方說我們在<code>dahaizi</code>資料庫下建立一個名為<code>test</code>的表:
那在資料庫<code>dahaizi</code>對應的子目錄下就會建立一個名為<code>test.frm</code>的用于描述表結構的檔案。值得注意的是,這個字尾名為.frm是以二進制格式存儲的
前邊重點唠叨過<code>innodb</code>的一些實作原理,到現在為止我們應該熟悉下邊這些東東:
<code>innodb</code>其實是使用<code>頁</code>為基本機關來管理存儲空間的,預設的<code>頁</code>大小為<code>16kb</code>。
對于<code>innodb</code>存儲引擎來說,每個索引都對應着一棵<code>b+</code>樹,該<code>b+</code>樹的每個節點都是一個資料頁,資料頁之間不必要是實體連續的,因為資料頁之間有<code>雙向連結清單</code>來維護着這些頁的順序。
<code>innodb</code>的聚簇索引的葉子節點存儲了完整的使用者記錄,也就是所謂的索引即資料,資料即索引。
為了更好的管理這些頁,設計<code>innodb</code>的大叔們提出了一個<code>表空間</code>或者<code>檔案空間</code>(英文名:<code>table space</code>或者<code>file space</code>)的概念,這個表空間是一個抽象的概念,它可以對應檔案系統上一個或多個真實檔案(不同表空間對應的檔案數量可能不同)。每一個<code>表空間</code>可以被劃分為很多很多很多個<code>頁</code>,我們的表資料就存放在某個<code>表空間</code>下的某些頁裡。設計<code>innodb</code>的大叔将表空間劃分為幾種不同的類型,我們一個一個看一下。
這個所謂的<code>系統表空間</code>可以對應檔案系統上一個或多個實際的檔案,預設情況下,<code>innodb</code>會在<code>資料目錄</code>下建立一個名為<code>ibdata1</code>(在你的資料目錄下找找看有木有)、大小為<code>12m</code>的檔案,這個檔案就是對應的<code>系統表空間</code>在檔案系統上的表示。怎麼才<code>12m</code>?這麼點兒還沒插多少資料就用完了,哈哈,那是因為這個檔案是所謂的<code>自擴充檔案</code>,也就是當不夠用的時候它會自己增加檔案大小~
當然,如果你想讓系統表空間對應檔案系統上多個實際檔案,或者僅僅覺得原來的<code>ibdata1</code>這個檔案名難聽,那可以在<code>mysql</code>啟動時配置對應的檔案路徑以及它們的大小,比如我們這樣修改一下配置檔案:
這樣在<code>mysql</code>啟動之後就會建立這兩個512m大小的檔案作為<code>系統表空間</code>,其中的<code>autoextend</code>表明這兩個檔案如果不夠用會自動擴充<code>data2</code>檔案的大小。
在一個mysql伺服器中,系統表空間隻有一份
在mysql5.6.6以及之後的版本中,<code>innodb</code>并不會預設的把各個表的資料存儲到系統表空間中,而是為每一個表建立一個獨立表空間,也就是說我們建立了多少個表,就有多少個獨立表空間。使用<code>獨立表空間</code>來存儲表資料的話,會在該表所屬資料庫對應的子目錄下建立一個表示該<code>獨立表空間</code>的檔案,檔案名和表名相同,隻不過添加了一個<code>.ibd</code>的擴充名而已,是以完整的檔案名稱長這樣:
比方說假如我們使用了<code>獨立表空間</code>去存儲<code>xiaohaizi</code>資料庫下的<code>test</code>表的話,那麼在該表所在資料庫對應的<code>xiaohaizi</code>目錄下會為<code>test</code>表建立這兩個檔案:
其中<code>test.ibd</code>檔案就用來存儲<code>test</code>表中的資料和索引。當然我們也可以自己指定使用<code>系統表空間</code>還是<code>獨立表空間</code>來存儲資料,這個功能由啟動參數<code>innodb_file_per_table</code>控制,比如說我們想刻意将表資料都存儲到<code>系統表空間</code>時,可以在啟動<code>mysql</code>伺服器的時候這樣配置:
當<code>innodb_file_per_table</code>的值為<code>0</code>時,代表使用系統表空間;當<code>innodb_file_per_table</code>的值為<code>1</code>時,代表使用獨立表空間。不過<code>innodb_file_per_table</code>參數隻對建立的表起作用,對于已經配置設定了表空間的表并不起作用。如果我們想把已經存在系統表空間中的表轉移到獨立表空間,可以使用下邊的文法:
或者把已經存在獨立表空間的表轉移到系統表空間,可以使用下邊的文法:
其中中括号擴起來的<code>=</code>可有可無,比方說我們想把<code>test</code>表從獨立表空間移動到系統表空間,可以這麼寫:
随着mysql的發展,除了上述兩種老牌表空間之外,現在還新提出了一些不同類型的表空間,比如通用表空間(general tablespace)、undo表空間(undo tablespace)、臨時表空間(temporary tablespace)吧啦吧啦的,具體情況我們就不細唠叨了,等用到的時候再提。
nice to see you all!