MySql的數據目錄


數據目錄的位置

MySQL數據目錄的默認位置已經被編譯到MySQL服務器程序里了。

在啟動服務器時,通過使用一個--datadir=dir_name選項可以明確指定數據目錄位置。把MySQL數據目錄安排到其他地方的另一種辦法是把它列在MySQL服務器在啟動時會讀取的某個選項文件里。這樣,就不必在每次啟動MySQL服務器時都在命令行上寫出其數據目錄的路徑了。

如果你運行多個服務器,你應該知道它們各自的數據目錄在什么地方,但是如果你不知道確切的位置,可以用下面幾種方法把它查出來:

  1. mysqladmin -uroot -p123456 -P3306 -h127.0.0.1 variables | grep datadir

  2. show variables like 'datadir';

  3. ps axww | grep datadir

  4. 查看服務器在啟動時所讀取的選項文件,通常可以在[mysqld]選項組里看到一個下面這樣的datadir行:datadir=/path/to/data/directory

  5. 使用find命令搜索數據庫文件的辦法來查明MySQL服務器的數據目錄位置。尋找.frm(數據庫定義)文件:find / -name "*.frm" -print

數據目錄的結構

MySQL數據目錄收錄着MySQL服務器所管理的全部數據庫和數據表,這些文件被組織成一個樹狀結構,通過利用Unix或Windows文件系統的層次結構直接實現,即:

(1)每個數據庫對應於數據目錄下的一個目錄。

(2)同一個數據庫里的數據表對應於數據庫目錄中的各有關文件。

這種以目錄和文件來實現數據庫和數據表的層次化的做法有一個例外,即InnoDB數據表處理程序把所有數據庫里的所有InnoDB數據表全部存放在同一個公共表空間里。這個表空間是用一個或者多個非常大的文件而實現的,這些文件將被視為一個連接統一的數據結構,各InnoDB數據表的數據和索引都將存放在這個連接統一的數據結構中。在默認情況下,InnoDB表空間文件也都存放在MySQL數據目錄里。

MySQL數據目錄還可能包含有其他一些文件,例如:

(1)MySQL服務器的選項文件auto.cnf

(2)MySQL服務器的進程ID(PID)文件。

(3)MySQL服務器所生成的狀態和日志文件。

(4)把DES密鑰文件或服務器的SSL證書與密鑰文件存放在MySQL數據目錄也是常見的做法。

MySQL數據在文件系統里如何表示

MySQL服務器所管理的每一個數據庫都有它自己的數據庫目錄,這個數據庫目錄其實是MySQL數據目錄中的一個子目錄,這個子目錄的名字與它代表的數據庫名字相同。例如,對應於數據庫mydb的數據庫目錄就是DATADIR/my_db。這種表示方法使MySQL數據庫系統中一些與數據庫有關的語句實現起來相當簡單。

例如,CREATE DATABASE db_name命令將在MySQL數據目錄里創建一個名為db_name的空目錄。在UNIX系統上,新創建的目錄的屬主就是啟動MySQL服務器時使用的登錄賬戶,並且只能通過該登錄賬戶去訪問它。換而言之,CREATE DATABASE命令相當於在使用那個賬戶登錄到MySQL服務器主機上之后執行下列shell命令:

cd DATADIR

mkdir db_name

chmod u=rwx, go-rwx db_name

用一個空目錄來代表一個新數據庫可以說是最簡單的做法了。在其他的數據庫系統里,即使是創建一個“空的”數據庫也需要創建好幾個控制文件或系統文件。

DROP DATABASE語句實現同樣簡單。DROP DATABASE db_name刪除數據庫中的db_name目錄和所有表文件,這幾乎與下列命令一樣:

cd DATADIR

rm-rf DATADIR/db_name

DROP DATABASE語句與shell命令之間的區別如下:

  1. 如果使用的是DROP DATABASE命令,MySQL服務器僅通過查看有關文件的擴展名刪除那些與數據表有關的文件。如果還在數據庫目錄里創建過其他文件,MySQL服務器將保留這些文件,而且目錄本身也不會被刪除。
  2. InnoDB數據表及其索引的內容都存放在InnoDB表空間里,而不是被存放為MySQL數據目錄中的文件。如果某個數據庫里包含着InnoDB數據表,就必須使用DROP DATABASE語句才能讓InnoDB處理程序從InnoDB表空間里把該數據表刪掉,用rm或del命令刪除數據庫目錄的方法對InnoDB數據表是無效的。

MySQL數據在文件系統里如何表示

MySQL支持以下幾種針對不同數據表類型的處理程序:ISAM、MyISAM、MERGE、BOB、InnoDB和HEAP。MySQL中的每一個數據表在磁盤上至少被表示為一個文件,即存放着該數據表的結構定義的.frm文件;大部分數據表類型還有其他幾個用來存放數據行和索引信息的文件。這些文件會隨着數據表類型的不同而變化。

ISAM數據表

MySQL中最原始的數據表類型就是ISAM類型。在MySQL里,每個ISAM數據表用包含着該數據表的數據庫目錄里的三個文件來代表。這些文件的基本名與數據表的名字相同,擴展名則分別表明了有關文件的具體用途。例如:名為mytb1的ISAM數據表將被表示為以下三個文件:

mytb1.frm——定義文件,存放着該數據表的格式(結果)定義。

mytb.ISD——ISAM數據文件,存放着該數據表中的各個數據行的內容。

mytb.ISM——ISAM索引文件,存放着該數據表的全部索引信息。

MyISAM數據表

MySQL3. 23版本引入了MyISAM數據表類型作為ISAM類型的后繼者,MyISAM數據表類型也要使用三個文件來代表一個數據表,這三個文件的擴展名分別是.frm(結構定義文件)、.MYD(數據文件)和.MYI(索引文件)。

MERGE數據表

.MERGE數據表其實是一個邏輯結構。它代表着由一組結構完全相同的MyISAM數據表所構成的集合;有關的查詢命令將把它當作一個大數據表來對待。在數據庫目錄里,每一個MERGE數據表將被表示為一個.frm文件和一個.MRG文件,.MRG文件其實就是一份由各MyISAM數據表的名單構成的MERGE數據表。

BDB數據表

BDB處理程序用兩個文件來代表每個數據表,其一是用來存放數據表結構定義的.frm文件,其二是用來存放數據表的數據和索引信息的.db文件。

InnoDB數據表

上述幾種數據表類型都是用多個文件來表示一個數據表的。InnoDB數據表與它們有所不同。與一個給定InnoDB數據表直接對應的文件只有一個,即數據表的.frm結構定義文件,這個文件存放在包含着數據表的數據庫目錄里。所有InnoDB數據表的數據和索引都被存放到同一個專用的表空間里統一管理。一般來說,這個表空間本身將被表示為MySQL數據目錄里的一個或者多個大文件。構成表空間的這些文件將形成一個在邏輯上連續不斷的存儲區域,表空間的總長度等於各組成文件的長度之和。

HEAP數據表

HEAP數據表是創建在內存中的數據表。因為MySQL服務器把HEAP數據表的數據和索引都存放在內存里而不是存放在硬盤上,所以除相應的.frm文件外,HEAP數據表在文件系統里根本沒有相應的代表文件。

SQL語句如何映射為數據表文件操作

每一種數據表類型都要使用一個.frm文件來保存數據表的結構定義,所以,應用show table my_name命令所得到的輸出結果,與列出數據庫目錄db_name中所有.frm文件基本名所得到的結果是相同的。有些數據庫系統使用一個注冊表來記錄某數據庫里的所有數據表,但MySQL沒有這樣做,因為,系統不需要這樣設置,MySQL數據目錄的層次結構已經把“注冊表”隱藏在其中了。

創建數據表

要想創建一個MySQL所支持的任意類型的數據表,需要發出一條CREATE TABLE語句定義數據表的結構。無論哪一種數據表類型,MySQL服務器都將創建一個.frm文件來保存數據表的結構定義的內部編碼。MySQL服務器還會根據指定數據表的具體類型創建出其他必要的文件。例如,它將為一個MyISAM數據表創建出一個.MYD數據文件和一個.MYI索引文件;為一個BDB數據表創建出一個.db數據/索引文件。對於InnoDB數據表,InnoDB處理程序將在InnoDB表空間里為數據表初始化一些數據和索引信息。在UNIX系統上為新數據表而創建的各個文件的屬主和存在模式將被設置為只允許用來運行MySQL服務器的賬戶進行訪問。

更新數據表

當發出一條ALTER TABLE tbl_name語句時,MySQL服務器將對有關數據表的.frm文件重新進行編碼以反映出這條語句所表明的結構性變化,還要對有關的數據文件和索引文件的內容進行相應的修改。CREATE INDEX和DROP INDEX也是一樣能引起類似的動作,因為MySQL服務器在內部是把它們當作等效的ALTER TABLE語句來處理的。改變InnoDB數據表的結構會引起InnoDB處理程序修改InnoDB表空間中數據表的數據,同時也對索引做出相應的修改。

刪除數據表

DROP TABLE語句是通過刪除代表該數據表的各種有關文件而實現的。丟棄一個InnoDB數據表將是數據表在InnoDB表空間里占用的空間被標注為“未使用”。

對於某些數據表類型,可以通過在相應的數據庫目錄里刪除與數據表有關的各個文件的辦法來手動刪除這個數據表,例如,假設mydb是當前數據庫,mytb1是一個ISAM、MyISAM、BOB或MERGE數據表,那么drop table mytb1語句就大致等效於下面這兩條UNIX命令:

cd DATADIR

rm -f mydb/mytb1.*

對於InnoDB或HEAP數據表,因為它們的某些組成部分在文件系統里沒有實體性的文件來代表,所以針對這兩種數據表類型的DROP TABLE語句沒有等效的文件系統級命令。例如,InnoDB數據表在文件系統里只有一個相應的.frm文件,用文件系統級命令刪除這個文件將使該數據表在InnoDB表空間數據和索引成為“流離失所的孤兒”。

操作系統對數據庫和數據表命名的限制

MySQL對數據庫和數據表的命名有其自己的一套命名規則,下面是命名中的幾個要點:

(1)名字可以由當前字符集中的字母和數字字符以及下划線(_)和美元符號($)構成。

(2)名字的最大長度是64個字符。

從MySQL3.23.6版本開始,其他字符也可以出現在名字里,但它們必須用反引號引起來。如果想把保留字用做數據列的名字,那最好用反引號把它們引起來。可是,因為數據庫和數據表的名字將被MySQL用做相應的目錄和文件的基本文件名,所以數據庫和數據表的名字往往還要遵守MySQL服務器在其運行的操作系統中的文件系統命名規則的限制,譬如($在linux是特殊字符,大小寫敏感)。

數據目錄的結構對系統性能的影響

MySQL數據目錄的結構很容易理解,因為它以一種相當自然的方式使用文件系統的層次結構。但這種結構對性能也有着隱含的影響。因為每打開一個數據表都需要打開一個或者多個與該數據表相關聯的文件,所以這種層次結構對性能往往會產生很大的影響。

MySQL數據目錄的結構繁多,這將導致數據表處理程序需要使用多個文件來代表一個數據表,而打開一個數據表需要用到多個而不是一個文件描述符。MySQL服務器智能化地將文件描述符緩存起來,但一個繁忙的MySQL服務器仍有可能因為需要同時向多個客戶連接提供服務器,或者執行一些涉及多個數據表的復雜查詢而耗盡文件描述符,這很可能會是一個問題。因為文件描述符在許多系統,尤其是那些把每個進程所能使用的文件描述符個數(即允許每個進程打開的文件個數)設置得相當低的系統上都是一種稀缺的資源。

用多個文件來代表一個數據表的做法還會導致數據表打開操作的時間隨查詢命令所涉及的數據表個數的增加而延長。因為MySQL里的數據表打開操作將被映射為操作系統中的無連接打開操作,所以系統目錄搜索例程的執行效率就會影響到數據表打開操作的執行效率。這一般算不上是個問題,但如果數據庫里有很多個數據表的話,這個因素就很值得考慮了。例如,我們知道,每個MyISAM數據表都將被表示為3個文件。假如數據庫里有10000個MyISAM數據表,則數據庫目錄就將有30000個文件,用戶就肯定會注意到文件打開操作明顯地慢了下來。(Linux ext2和Solaris文件系統會遇到這個問題)。如果系統性能因此而下降到足以引起關注的程度,就應該考慮換用一種能夠高效率地處理大量文件的文件系統。例如,ReiserFS文件系統就是一種在存在大量小文件的情況下,依然有着良好性能的文件系統。如果系統無法換用另一種文件系統,就應該根據應用軟件的具體情況重新考慮那些數據表的結構,對數據表的結構做出必要的優化調整。例如,如果應用軟件要為每個用戶分別創建一個數據表,數據庫里就會有很多結構完全相同的數據表。要想把這些數據表合並為一個數據表,可能需要增加一個數據列以表明各有關數據行都對應於哪一位用戶。如果能大大減少數據表的數量,應用軟件的性能就會有明顯的改善。

用盡可能少的文件創建出多個數據表的辦法是使用InnoDB數據表。每個InnoDB數據表只有一個與之相關聯的.frm文件,所有InnoDB數據表的數據和索引信息都將存放在InnoDB表空間里。這就大大減少了用來表示InnoDB數據表的磁盤文件的數量,進而減少了打開一個數據表時需要用到的文件描述符的個數。當用到InnoDB數據表的時候,InnoDB處理程序會先打開構成InnoDB表空間的各個組成文件(InnoDB表空間由幾個組成文件構成,就要用到幾個文件描述符;但這個數字在服務器運轉期間將是一個常數);然后,每打開一個InnoDB數據表,InnoDB處理程序就要用一個文件描述符去打開該表的.frm文件,每關閉一個InnoDB數據表,與該數據表相關聯的文件描述符就會被釋放。

MySQL狀態文件和日志文件

除數據庫目錄外,MySQL數據目錄里還包含許多狀態文件和日志文件,這些文件默認存放位置是相應的MySQL服務器的數據目錄,其默認文件名是在服務器主機名上增加一些后綴而得到的。

1.進程ID文件

MySQL服務器會在啟動時把自己的進程ID寫入PID文件,等運行結束時又會刪除該文件。PID文件是允許服務器本身被其他進程找到的工具。例如,如果運行mysql.server,在系統關閉時,關閉MySQL服務器的腳本檢查PID文件以決定它需要向哪個進程發出一個終止信號。

2.MySQL日志文件

MySQL能夠維護多個不同的日志文件。大多數日志功能都是可選的;不僅可以在啟動MySQL服務器時利用各種啟動選項來激活日志(對不常用的日志可以不啟用),還可以指定日志文件的名字。

(1)常規日志記錄服務器操作的綜合性信息;哪些人正從哪些地方試圖連接MySQL服務器、他們發出哪些查詢命令等。

(2)變更日志記錄查詢命令信息,但它只記錄那些對數據庫內容做出可修改的查詢命令。變更日志的內容是一些SQL語句,可以把這些語句提供給mysql客戶程序作為輸入以執行。

(3)二進制變更日志與變更日志作用相同,但其內容是用效率更高的二進制格式寫出來的。附屬的二進制日志索引文件列出了MySQL服務器當前正在維護着哪些二進制日志文件。

變更日志和二進制變更日志主要用於MySQL數據庫系統的崩潰恢復工作中。在發生系統崩潰后,先用備份文件把數據庫恢復到當初進行備份時的狀態,再把變更日志或二進制變更日志的內容寫入MySQL服務器,讓它再次執行日志中記載的各種修改操作,把數據庫恢復到崩潰發生時所處的狀態。

例如:下面的日志記錄了在test數據庫中創建一個my_tabl表,插入一行數據,然后刪除表的會話:

990509 7:37:09 492 Connect Paul@localhost on test

492 Query CREATE TABLE my_tbl(val INT)

492 Query INSERT INTO my_tbl values(1)

492 Query DROP TABLE my_tbl

492 Quit

常規日志中的信息由以下幾項內容組成:日期/時間、服務器線程(連接)ID、事情的類型、事情的具體信息。如果后一事件與前一事件的發生日期/時間相同,則后一事件在常規日志中的記錄項將省略日期/時間字段。

同一個會話出現在更新日志中看上去如下所示:

use test;

CREATE TABLE my_tbl(val int);

INSERT INTO my_tbl VALUES(1);

DROP TABLE my_tbl;

(4)對更新日志,用--log-long-format選項獲得一個擴展形式的日志,擴展日志提供有關誰何時發出每一條查詢,這使用更多的磁盤空間,但如果你想知道誰在做什么,而不用將更新日志對照一般日志的內容找到連接事件。對上面的會話,擴展更新日志產生這樣的信息:

#Time:990507 7:32:42

#User@Host:paul[paul]@localhost[]

use test;

CREATE TABLE my_tbl(val int);

#User@Host:paul[paul]@localhost[]

INSERT INTO my_tbl VALUES(1);

#Time:990507 7:32:43

#User@Host:paul[paul]@localhost[]

DROP TABLE my_tbl;

ps:新增加的記載內容都寫在了以“#”字符開頭的行上。這樣,當把變更日志饋入mysql客戶程序以傳遞給MySQL服務器去執行時,它們將被解釋為注釋。

(5)錯誤日志記載着MySQL服務器在發生異常情況時生成的診斷信息。如果MySQL服務器啟動失敗或意外退出,通常可以從這個日志里了解到其原因。

日志文件的尺寸有可能變得非常大,一定要保證它們不至於填滿文件系統。可以定期使一些日志文件失效以保證它們使用的空間總量不會超過一定的界限。

因為日志文件中記載的查詢命令里可能會有口令之類的敏感信息,所以應該注意加強日志文件的安全保護工作,避免它們遭受意外破壞或者被無關用戶讀取。例如,下列日志項里就用root用戶的口令,這一定不是想讓任何人看到的信息:

990509 7:23:31 4 Query UPDATE user SET

Password=PASSWORD("secret")

WHERE user="root"

在默認的情況下,日志將被寫到MySQL數據目錄里,所以加強日志文件的安全保護工作的主要措施之一就是不讓MySQL管理員的登錄賬戶進入並看到MySQL數據目錄里的內容。

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM