[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 數據庫 > MySQL > 正文
MySQL數據目錄結構
不詳 (2001-05-14 03:28:00)

從概念上講,大多數關系數據庫系統是相似的:它們有一系列數據庫組成,每個數據庫包含一系列數據庫表,但每個系統有各自組織其管理的數據方式,MySQL也不例外。  

缺省地,所有由MySQL服務器mysqld管理的數據存儲在一個稱為MySQL數據目錄的地方,所有數據庫都存放在哪兒,也包括提供服務器操作信息的狀態文件。如果你對一個MySQl安裝執行管理任務,你應該熟知數據目錄的布局及用途。  

本文介紹下列專題:  

如何確定數據目錄的位置。  
服務器如何組織並提供對數據庫和它管理的表的訪問。  
在哪裡找到由服務器生成的狀態文件記憶它們包含什內容。  
如何改變缺省地點或數據目錄或單獨數據庫的組織結構。  
1、數據目錄的位置  
一個缺省數據目錄被編譯進了服務器,如果你從一個源代碼分發安裝MySQL,典型的缺省目錄為/usr/local/var,如果從RPM文件安裝則為/var/lib/mysql,如果從一個二進制分發安裝則是/usr/local/mysql/data。  

在你啟動服務器,通過使用一個--datadir=/path/to/dir選項可以明確指定數據目錄位置。如果你想把數據目錄置其它缺省位置外的某處,這很有用。  

作為一名MySQL管理員,你應該知道你的數據目錄在哪裡。如果你運行多個服務器,你應該是到所有數據目錄在哪裡,但是如果你不知道確切的位置,由多種方法找到它:  

使用mysqladmin variables從你的服務器直接獲得數據目錄路徑名。查找datadir變量的值,在Unix上,其輸出類似:  
%mysqladmin variables  

+----------------------+----------------------+  
| variable_name | Value |  
+----------------------+----------------------+  
| back_log | 5 |  
| connect_timeout | 5 |  
| basedir | /var/local/ |  
| datadir | /usr/local/var/ |  
....  
在Windows上,輸出可能看上去像這樣:  
c:\mysqladmin variables  

+----------------------+----------------------+  
| variable_name | Value |  
+----------------------+----------------------+  
| back_log | 5 |  
| connect_timeout | 5 |  
| basedir | c:\mysql\ |  
| datadir | c:\mysql\data\ |  
....  
如果你有多個服務器在運行,它們將在不同的TCP/IP端口或套接字上監聽,通過提供連接服務器正在監聽的端口或套接字的--port或--socket選項,你可以輪流獲得它們每一個的數據目錄信息:  

%msqladmin --port=port_name variables  

%mysqladmin --socket=/path/to/socket variables  

mysqladmin命令可運行在任何你能從其連接服務器的主機上,如果你想在一個遠程主機連接服務器,使用一個--host=host_name選項:  

%mysqladmin --host=host_name variables  

在Windows上,你可以通過使用--pipe強制一個命令管道連接和--socket=pipe_name指定管道名來連接監聽一個命令管道的NT服務器:  

c:\mysqladmin --pipe --socket=pipe_name variables  

你可以使用ps命令查看任何正在運行mysqld 進程的命令行。  
試一下下列命令之一並尋找--datadir:  

%ps axww | grep mysql BSD風格  

%ps -ef | grep mysqld System V風格  

如果你的系統運行多個服務器,ps命令可能特別有用,因為你能馬上發現多個數據目錄位置,缺點是必須在服務器上運行,而且可能沒有有用的信息產生,除非在mysqld命令行上明確指定了--datadir選項。  

如果MySQL是從一個源代碼分發安裝的,你可以檢查其配置信息確定數據目錄位置。例如,位置可從頂級Makefile中獲得,但是注意,位置是Makefile中的localstatedir值,不是datadir,而且,如果分發位一個NFS掛載的文件系統並用來為多個主機構建MySQL,配置信息反映了分發被最新構建的主機,這可能不能提供你感興趣的主機的數據目錄信息。  
如果上述方式失敗,你可以用find尋找數據庫文件,下列命令尋找“.frm”文件,它是任何MySQL安裝的一部分:  

% find / -name ".frm" -print  

在下文各例中,用DATADIR表示MySQL數據目錄位置。  
2、數據目錄結構  
MySQL數據目錄包含了服務器管理的所有數據目錄,這些文件被組織成一個樹狀結構,通過利用Unix或Windows文件系統的層次結構直接實現。  

每個數據庫對應數據目錄下的一個目錄。  
在一個數據庫中的表對應數據目錄下的文件。  
數據目錄也包含由服務器產生的幾個狀態文件,如日志文件。這些文件提供了關服務器操作的重要信息。對管理特別在出了問題而試圖確定問題原因時很有價值。例如,如果某個特定查詢殺死服務器,你可以通過檢查日志文件判別搗亂的查詢。  

2.1 MySQL服務器怎樣提供對數據的訪問  
在數據目錄下的一切由一個單獨的實體-MySQL服務器mysqld管理,客戶程序絕不直接操作數據。相反,服務器提供數據可訪問的切入點,它是客戶程序與它們想使用的數據之間的中介。  

當服務器啟動時,如果有需要,它打開日志文件,然通過監聽網絡連接位數據目錄呈現一個網絡接口。要訪問數據,客戶程序建立對服務器的一個連接,然以MySQL查詢傳輸請求來執行希望的操作。服務器執行每一個操作並將結果發回用戶。服務器是多線程的並能服務多個同時的客戶連接。然而,因為修改操作一個執行一個,實際效果是順序化請求,以使兩個客戶決不能在同一時刻改變同一記錄。  

在正常的情況下,讓服務器作為數據庫訪問的唯一仲裁者提供了避免可從同時訪問數據庫表的多個進程的破壞的保証。管理員應該知道有時服務器沒有對數據目錄的獨裁控制。  

當你在一個單個數據目錄上運行多個服務器。一般倪雲新一個服務器管理主機上的所有數據庫,但是有可能運行多個服務器。如果這完成提供對多個獨立數據目錄的訪問,沒有相互影響的問題,但喲也能啟動多個服務器並指向同一個目錄。一般地,這不是一個好主意。如果你試圖這樣,最好是你的系統提供良好的文件鎖定功能,否則服務器將不能正確協作。如果你將多個服務器同時寫入日志文件,你也冒著你的日志文件稱為混亂的根源的風險。  
在你運行isamchk和myisamchk時。isamchk和myisamchk實用程序用表的維護、診錯和修復,就想你想的那樣,因為這些程序可以修改表內容,允許它們與服務器正在操作的同時對表操作,這樣能導致表損壞。理解如何限制這種相互影響是很重要的,這樣你不會損壞你的表。  
2.2 數據目表示  
每個MySQL服務器管理的數據庫有自己的數據庫表,它是數據目錄下的一個子目錄,其名字與它表示的數據庫相同。例如數據庫my_db對應數據庫目錄DATADIR/my_db。  

這種表示允許多個數據庫級的語句在其實現中十分簡單。CREATE DATABASE db_name在數據目錄中創建一個db_name空目錄,具有只允許MySQL服務器用戶(運行服務器的Unix用戶)的屬主和模式,這等價下列手工在服務器主機上創建數據庫:  

%mkdir DATADIR/db_name  
%chmod 700 DADADIR/db_name  
用一個空目錄表示一個新數據庫的最簡單方法與其它數據庫甚至為一個空數據庫創建大量的控制文件或系統文件正好相反。  

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

%rm -rf DATADIR/db_name  
(差別是服務器只刪除具有已知用表的綴名的文件。如果你在數據庫目錄創建了其它文件。則服務器保留它們,而且目錄本身不被刪除。  

SHOW DATABASE基本上不做什,只是列出位數據目錄中的目錄名。有些數據庫系統保持一個主表,用維護所有數據庫,但在MySQL無此構件。由賦予數據目錄結構的簡潔性,數據庫列表隱含在數據目錄的內容中,而且這樣的表不必有額外的開銷。  

2.3 數據庫表的表示  
每個數據庫在數據庫目錄中有3個文件:一個樣式(描述文件)、一個數據文件和一個索引文件。每個文件的基本名是表名,文件名擴展名代表文件類型。擴展名如下表。數據和索引文件的擴展名指出表使用老式IASM索引或新式MyISAM索引。  

表 MySQL文件類型  
文件類型 文件名擴展名 文件內容  
樣式文件 .frm 描述表的結構(它的列、列類型、索引等)。  
數據文件 .ISD(ISAM)  
或.MYD(MyISAM) 包含數據文件上的所有索引的索引樹。  
索引文件 .ISM(ISAM)  
或.MYI(MyISAM) 該索引文件依賴表是否有索引而存在。  

當你發出一條CREATE TABLE tbl_name時語句定義表的結構時,服務器創建一個名為tbl_name.frm的文件,它包括該結構的內部編碼,同時也創建一個空數據和索引文件,初始化為包含指出無記錄和無索引的信息(如果CREATE TABLE語句包括索引指定,索引文件反映出這些索引)。對應表的文件的屬主和模式被設置為只允許MySQL服務器用戶訪問。  

當你發出一條ALTER TABLE tbl_name語句時,服務器重新編碼tbl_name.frm,並修改數據和索引文件的內容以反映語句指定的結構改變。對CREATE INDEX和DROP INDEX也是一樣,因為它們被服務器視為與ALTER TABLE等價。DROP TABLE通過刪除對應表的三個文件來實現。  

雖然你可以通過刪除數據庫目錄中對應表的三個文件,但不能手工創建或修改一個表,如,如果my_db是當前數據庫,DROP TABLE my_tbl大概等價下列命令。  

% rm -rf DATADIR/my_db/my_tbl.*  

SHOW TABLE my_db的輸出只是列出my_db數據庫目錄中的.frm文件的基文件名。有些數據庫系統一個注冊表,列舉所有包含在一個數據庫中的表,MySQL不是,因為不必要,“注冊表”隱含在數據目錄的結構中。  

2.4 操作系統對數據庫和表命名的限制  
MySQL對命名數據庫和表有一個原則:  

名字可以由當前字符集中的任何字母數字字符組成,下劃線和美元符$也可以。  
名字最長為64個字符。  
然而,因為數據庫和表的名字對應目錄和文件名,服務器運行的操作系統可能強加額外的限制。  

首先,數據庫和表名僅限對文件名合法的字符,如$在MySQL的原則中是允許的,但是如果你的操作系統不允許,則你不能在目錄或表名中使用它。實際上,這對Unix或Windows不是所擔心的,最大的難度是在執行數據庫管理時直接在shell中引用名字,例如,如果你命名一個數據庫如$my_db,包含一個美元符,任何從shell中對該名字的引用可能被shell解釋為對一個變量的引用:  

%ls $my_db  
my_db:undefined variable  

對此,你必須轉義$字符或用引號禁止其特殊含義:  

%ls \$my_db  
%ls $my_db  

如果你用引號,一定要用單引號,而雙引號並不禁止變量解釋。  

其次,雖然MySQL允許數據庫和表名最長到64個字符,但名字的長度受限你的操作系統限定的長度,一般這不是一個問題(雖然老的System V強制14個字符)。在這種情況下,你數據庫名的上限為14個字符,而表名上限為10個字符,因為表示表的文件名有一個點(.)和三個字符的擴展名。  

第三,文件系統的大小寫敏感性影響到你如何命名和引用數據庫和表名。如果文件系統是大小寫敏感的(如Unix),兩個名字my_tbl和MY_TBL是不同的表。如果文件系統不是大小寫敏感的(如Windows),這兩個名字指的是相同的表。如果你用一個Unix服務器開發數據庫,並且如果你有可能轉移到Windows,你應該記住這一點。  

2.5 MySQL狀態文件  
除了數據庫目錄,MySQL數據目錄還包含很多狀態文件,這些文件總結在下表中。大多數文件的缺省名從服務器主機名生成,在下表中表示為HOSTNAME。  

表 MySQL狀態文件  
文件類型 缺省名 文件內容  
進程ID HOSTNAME.pid 服務器進程的ID  
出錯日志 HOSTNAME.err 啟動和關閉事件和出錯情況  
一般日志 HOSTNAME.log 連接/斷開事件和查詢信息  
更新日志 HOSTNAME.nnn 修改表結構級內容的所有查詢文本  

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

出錯日志由safe_mysqld創建,作為服務器標準出錯輸出的重定向,它包含任何邪到stderr的消息。這意味著只有你通過調用safe_mysqld啟動服務器,出錯文件才存在(無論如何,它是一個啟動服務器的最好方法,因為如果它由出錯而退出,safe_mysqld將重啟服務器。)。  

一般日志和更新日志是可選的。你可以只開啟你需要的日志類型,用--log和--log-update服務器選項。  
一般日志提供服務器操作的一般信息:誰從哪裡連接服務器和他們發出什查詢。更新日志提供查詢信息,但只有修改數據庫內容的查詢。更新日志內容被寫成SQL語句,可以將它們提供給mysql客戶程序來執行。如果你遇上崩潰,並且必須倒回備份文件,更新日志就很有用,因為你能重復執行自崩潰時的更新,通過將更新日志反饋給服務器,這允許你將數據庫恢復到崩潰發生時的狀態。  

下面是一個簡單的例子,信息出現在一般日志中,它是一個創建一個在數據庫test中表,插入一行,然刪除表的會話:  

990509 7:37:09 492 Connect Paul@localhost on test  
492 Query show databases  
492 Query show tables  
492 Field List tbl_1  
492 Field List tbl_2  
...  
990509 7:34:22 492 Query CREATE TABLE my_tbl (val INT)  
990509 7:34:34 492 Query INSERT INTO my_tbl values (1)  
990509 7:34:38 492 Query DROP TABLE my_tbl  
990509 7:34:40 492 Quit  
一般日志包含日期和時間、服務器進程ID、事件類型和事件信息欄目。  

同一個會話出現在更新日志中看上去像這樣:  

use test;  
CREATE TABLE my_tbl (val int);  
INSERT INTO my_tbl VALUES(1);  
DROP TABLE my_tbl;  
對更新日志,用--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;   
保証你的日志文件安全並且不讓任意用戶讀取是個好主意。一般日志和更新日志都能包含諸如口令等的敏感信息,因為它們包含查詢文本。如:  

990509 7:23:31 4 Query UPDATE user SET Password=PASSWORD("secret")  
WHERE user="root"  
對檢查和設置數據目錄的權限,請見《MySQL安全性指南》。使數據目錄安性的指令包含下列命令:  

% chmod 700 DATADIR  

以擁有數據目錄的Unix用戶運行此命令。確保服務器也以此用戶運行,否則該命令不僅將其它人拒之門外,它也阻止服務器訪問你的數據庫。  

狀態文件出現在數據目錄的頂級目錄,就象數據庫目錄,所以你可能擔心這些文件名是否與數據庫名沖突或出錯(如在服務器執行SHOW DATABASES語句時)。答案是不。狀態和日志文件信息存儲在文件中,而數據庫是目錄,所以可執行程序能用一個簡單的stat()調用區分它們。如果你看一下數據目錄,你可以區分狀態文件和數據庫目錄,用ls -l並檢查模式的第一個字符是一個"_"還是一個"d"。  

你也可以簡單地看一下名字,所有狀態文件名包含一個點("."),而數據庫目錄沒有(.在數據庫名中是無效字符)。  

(http://www.fanqiang.com)
    進入【UNIX論壇

相關文章

======
 

★  樊強制作 歡迎分享  ★