MySQL數據庫——配置文件、日誌文件、套接字文件、pid文件、表結構文件、存儲引擎文件

目錄

1、配置文件

2、日誌文件

2.1、錯誤日誌文件

2.2、慢查詢日誌文件

2.3、查詢日誌 

2.4、二進制日誌

3、套接字文件

4、PID文件

5、表結構定義文件

6、存儲引擎文件

6.1、表空間文件

6.2、redo日誌文件

6.3、表文件的結構


1、配置文件

配置文件裏是MySQL數據庫的全局參數,指定了MySQL啓動時的各種配置,比如緩存池的大小,緩存池實例數量,日誌文件大小(位置),等等。配置文件就是之前博客裏講的(linux下)my.cnf 或者(windows下)my.ini。

配置文件裏的參數按照在運行期間是否可以被修改分爲 靜態參數動態參數。靜態參數是在數據庫運行期間無法修改的,如果要修改靜態參數,只能在配置文件裏修改,然後重啓數據庫。動態參數是在數據庫運行期間可以修改的。

按照參數的作用範圍可以分爲 會話參數全局參數。比如用戶A修改了某個參數,並且讓該參數只在當前用戶會話中起作用,假如有另一個用戶B登錄了數據庫,那麼B看到的該參數值仍然是舊值。有些參數只允許在會話中起作用,有些參數卻只能是全局參數,而還有些參數既可以作爲會話參數,又可以作爲全局參數。

怎麼查看這些參數 和 設置這些參數呢?

1、查看參數。

用 sql 指令,舉個例子  SHOW GLOBAL innodb_buffer_pool_size;  或者 SELECT  @@global.innodb_buffer_pool_size;   查看 innodb_buffer_pool_size 的全局值。   SHOW SESSION innodb_buffer_pool_size;  或者 SELECT  @@session.innodb_buffer_pool_size;     查看 innodb_buffer_pool_size 的會話值。

另外,還可以直接看 全局參數視圖 和 用戶會話參數視圖,分別在 performance_schema 庫裏的 global_variables表 和 user_variables_by_thread 表。

2、設置參數

用 sql 指令,舉個例子   SET  GLOBAL   innodb_buffer_pool_size = 1024;   或者  SET  @@global.innodb_buffer_pool_size = 1024; 

2、日誌文件

2.1、錯誤日誌文件

雖然叫錯誤日誌文件,但是並非所有的錯誤都會記錄,另外,還會記錄一些非錯誤信息,比如數據庫的啓動過程,關閉過程,數據庫在運行中的關鍵錯誤,一些警告信息等。總之,記錄的是需要我們注意且具有警示意義的信息。通過錯誤日誌文件可以快速定位錯誤,查明原因。

查看錯誤日誌文件,看看幾個全局參數:

log_error:表示數據庫的錯誤日誌文件位置和名字,默認文件名爲主機名,後綴爲 .err。

log_error_verbosity:表示錯誤日誌文件記錄哪種信息,1 表示只記錄錯誤, 2 表示記錄錯誤和警告, 3 表示記錄錯誤,警告 和 通知。默認爲 3。

有些老版本里面,還有log_warnings 參數,這個和 log_error_verbosity 作用差不多,應該沒有 log_error_verbosity 好,所以新版本已經刪除了 log_warnings 參數。

2.2、慢查詢日誌文件

慢查詢日誌文件是對於優化數據庫特別重要的日誌文件,數據庫有個全局參數 long_query_time ,是一個時間閾值,在數據庫運行期間,只要某個sql語句執行的時間超過了(大於,等於都不行) long_query_time,就被認定爲慢查詢語句並被記錄到慢查詢日誌中,因此,我們可以查看慢查詢日誌文件,分析那些執行時間久的sql語句,對它們進行優化,提升性能。

long_query_time 的單位是秒,但是小數點後面有6位,因此,可以精確到微秒。默認爲10秒。 這個時間是可以設置的。 

slow_launch_time:如果建立線程的時間超過了2秒,也會記錄到慢查詢日誌文件。

slow_query_log:是否開啓慢查詢日誌,默認不開啓。

slow_query_log_file:慢查詢日誌文件的名字和路徑。默認名字爲“主機名-slow.log”。

log_queries_not_using_indexes:是否開啓,如果SQL語句沒有用到索引,也會記錄到慢查詢日誌。默認不開啓。

log_throttle_queries_not_using_indexes:在 log_queries_not_using_indexes 開啓的情況下,限制每分鐘沒有使用索引的SQL語句記錄到慢查詢日誌的次數,0表示沒有限制。因爲在某些情況下,可能一分鐘內沒有用到索引的SQL語句會很多,導致慢查詢日誌文件急速增大,爲了限制一下,纔有了這個全局參數。

一般情況下,慢查詢日誌都是存儲於日誌文件中,但是時間一長,慢查詢日誌是非常多的,我們查看日誌文件也就不方便了,MySQL數據庫給了一個命令 mysqldumpslow ,專門用於處理慢查詢日誌和全文搜索慢查詢日誌。具體用法百度吧。

從MySQL 5.1 版本開始,可以運行將慢查詢日誌存儲於一張表中,這張表爲 mysql 庫下的 slow_log 表。數據庫默認是存於慢查詢日誌文件中,如何設置才能讓慢查詢日誌存於表中呢? 有一個全局參數 log_output,默認爲 FILE,表示文件形式, 如果設置爲TABLE,就表示存於表中。放在表中的好處是,表的每個列代表日誌的一個關鍵信息,我們可以使用 sql 語句更加方便,靈活地去讀取和處理慢查詢日誌。

slow_log 慢查詢日誌表 的存儲引擎默認是 CSV, CSV引擎的特點就是以csv文件作爲MySQL表,沒有索引,不適合大數據表。因此,如果要用表格去存慢查詢日誌,就把slow_log 表的引擎換一個,能夠支持索引,方便大數據量的處理就行。如果不熟悉 sql 指令,建議安裝一個 Navicat,圖形化操作數據庫,並且也支持使用 sql 。如果用 SQL 去換一張表的存儲引擎,舉個例子:ALTER TABLE mysql.slow_log  ENGINE = InnoDB。

另外,還有一點需要注意,在比較新的版本中,MySQL支持另一種判斷慢查詢語句的標準,即 long_query_io 全局參數,表示邏輯讀取次數,不急,慢慢道來。在之前的版本的中,用SQL語句的執行時間來作爲衡量標準,而且已經精確到微秒了,爲什麼還要搞一個 long_query_io 出來呢?原因在於引擎的運行不是穩定的,有時候業務量大,給人的感覺就忙一點(卡一點),有時候沒什麼事幹,就空閒一點,所有在忙的時候,我們執行一條SQL的時間很可能要久一點,也許就因爲久這一點,這條SQL就被認定爲慢查詢SQL了。因此,將SQL語句的執行時間作爲評判標準,一般來講沒什麼問題,只不過偶爾也會有誤判。所以,在新版本中,纔會出現了long_query_io 評判標準,推出兩個概念,邏輯讀取 和 物理讀取,物理讀取次數 是指需要磁盤進行的IO次數,邏輯讀取次數 是指物理讀取次數 + 緩存池讀取次數, long_query_io 的使用就表示,不管你執行時間是多少,我只看你是不是比較費資源,費性能(因爲你讀取次數多呀),也許有條SQL在數據庫空閒時執行的,雖然執行時間短一些,但是它卻可能會消耗不少讀取次數。

當然,新版本是兼容老版本的,你可以在新版本中指定慢查詢評判標準是 long_query_time, 也可以設置評判標準爲 long_query_io,怎麼設置呢?新版本中有一個全局參數 slow_query_type,決定了用哪種方式: 0 表示不開啓慢查詢日誌,1 表示將時間作爲標準, 2 表示將邏輯讀取次數作爲標準,3 表示將兩個都作爲評判標準,只要 SQL 超過了任意一個標準,都會被認爲是慢查詢。

2.3、查詢日誌 

查詢日誌沒有什麼特殊的,但凡是用戶對數據庫的請求,查詢日誌統統記錄下來(包括一些SQL執行出錯的信息),在開發過程中,我也經常通過查看這個日誌文件來判斷有些SQL語句是否執行了,成功與否等等。 下面兩個全局參數:

general_log :是否開啓查詢日誌,默認不開啓。

general_log_file:查詢日誌文件的名字和位置,默認爲主機名.log。

查詢日誌文件的內容是非常多的,如何查看呢?有一個 tail 指令,常用的就是 tail -n 500 xxx.log, 用於查看日誌文件末尾最新的500行記錄。

另外,查詢日誌也可以存儲到表中,mysql 庫下的 general_log 表,怎麼設置呢?和慢查詢日誌的一樣,同一個參數 log_out 設置爲 TABLE 即可。

2.4、二進制日誌

二進制日誌文件用於存儲用戶對數據庫的所有DML操作,即凡是用戶對數據庫數據進行了修改的,都要存儲到二進制日誌文件中,比如 update, delete等等, 像 select,get,show 這些操作就不會記錄進二進制日誌文件。

log_bin:表示是否開啓二進制日誌,默認不開啓。

log_bin_basename:默認是主機名,表示二進制日誌文件的基礎名。因爲二進制日誌文件不止一個,所以會在基礎名後面加自增數字,來達到區分的目的。

log_bin_index:一個索引,通過這個索引可以找到和區分所有的二進制日誌文件。

開啓二進制日誌會影響一點點數據庫性能,官方測試,會使得數據庫性能下降 1%。但是二進制日誌會帶來如下幾個作用:

1、災備恢復。之前的博客已經介紹了當緩衝池中的事務數據丟失時,如何保證事務的redo,用redo日誌文件就可以保證。而此處的災備恢復是指,當數據庫磁盤裏的數據丟失了一段時間的數據,你咋整,比如數據庫爲了做災備工作,每隔一段時間都會把數據庫裏的所有數據進行一次備份,剛剛備份完,過了1個小時,磁盤毀壞了,裏面的數據全沒了,這就意味着這1個小時內的所有改動過的數據全沒了,如果有二進制日誌文件的話,我可以在備份的基礎,按照順序執行一遍二進制日誌裏的操作,就可以恢復了。

2、複製。這主要針對主從數據庫集羣的,主數據庫的數據要儘量及時地給到從數據庫,可以直接傳輸新的數據,也可以陪和着二進制日誌文件進行數據同步。

3、審計。因爲任何對數據庫改動的操作都會被記錄到二進制日誌中,如果有攻擊操作的話,就可以在日誌中看到。

3、套接字文件

在 Unix 或者 linux 系統裏,一切皆是文件,套接字也是如此,索引在 Unix 系統下,本地連接 MySQL 可以採用 UNIX 域套接字方式,需要一個套接字文件,一般在 /tmp/mysql.sock。

4、PID文件

pid 代表進程號,MySQL啓動時,即一個進程啓動了,會將進程的ID寫入一個文件,就是PID文件,MySQL的PID文件默認在如下位置。 pid_file 用於設置PID文件名和位置,默認名字爲主機名.pid。

5、表結構定義文件

數據庫表分爲兩部分內容,一部分是數據本身,另一部分是表的結構信息,MySQL有一種文件,後綴名爲 .frm,一個frm文件用於存儲一張表的結構 或者 一個視圖的結構。

6、存儲引擎文件

6.1、表空間文件

一個數據庫裏有很多表,一般來講,我們的業務數據表都是基於同一種引擎的,但是由於性能優化需要,可能有些表需要使用不同的存儲引擎,不同存儲引擎的表放在不同的地方,基於 InnoDB 引擎的那些表主要存放於兩個地方:1. 共享表空間文件, 2. 獨立表空間文件。

獨立表空間文件。innodb_file_per_table 參數用於是否啓動這種存儲方式,默認開啓,將每一張表都單獨存放一個獨立的表空間文件裏,文件名爲 表名.idb。存的都是表的數據、索引、插入緩存 BITMAP 信息。表其餘的信息還是存放在共享表空間文件裏。

共享表空間文件。這個文件是一定有的,如果 innodb_file_per_table 沒有開啓的話,那麼所有基於InnoDB 引擎的表都將存儲在共享表空間文件中,當然共享空間文件可以是多個,文件名以 ibdata 爲基礎名,後面數字自增即可,如下圖,ibdata1 爲文件名,12M爲初始大小,autoextend 爲自動增長文件大小。如果 innodb_file_per_table 開啓了的話,那麼共享表空間文件裏存儲的僅僅是那些基於 InnoDB 引擎的表的小部分信息,表的數據、索引、插入緩存 BITMAP 信息是存放在獨立表空間文件裏的。

6.2、redo日誌文件

每一個存儲引擎至少有一個redo日誌組,一個redo日誌組至少包含2個redo日誌文件,默認是 ib_logfile0 和 ib_logfile1。可以用叫作鏡像日誌組的技術將不同的redo日誌組存放於不同的磁盤上,提供可用性。

之前的博客已經講過,redo日誌的寫入是循環覆蓋地寫,比如 ib_logfile0 寫滿了,就寫ib_logfile1,等 ib_logfile0 寫滿了,在從ib_logfile0 開始覆蓋寫。

需要注意,redo日誌不要太大,雖然可以支持最大爲512G,但是總歸不要設置這麼大,因爲一個文件太大的話,搜索和查詢起來就比較慢。

6.3、表文件的結構

當創建一個數據庫後,會看到有一個數據庫名的文件夾生成,再創建一個表格後,會看到該文件夾下面生產了2個文件,一個文件是 frm文件,名字是表格名,另一個是 .idb 文件,名字也是表格名,

一個表文件分爲若種段,我認爲它是按功能分的,每一種段包含一種用途的數據,比如數據段,索引段,undo日誌段,由於InnoDB引擎下每張表都有主鍵,且索引用的是B+樹,所以數據段存的是B+樹的葉子節點,索引段存的是B+樹的非葉子節點。段是一個邏輯層面的概念,沒有大小限制。 下圖是表文件的示意圖,借用這篇文章的圖 https://www.jianshu.com/p/11e0361e9989

segment 段, extent 區,page 頁, row 行。

一個段包含若干區,區是代表磁盤上一塊連續的存儲空間,但是區與區之間不要求是連續的。一個區的大小固定是 1M,我想區的大小被設計爲固定的且爲1M,是因爲:我覺得磁盤由於頻繁的數據寫入和刪除,也會出現空間碎片化的情況,當然計算機會自動地整理這些碎片,但是整理也是需要花時間的,區的空間是需要找一塊連續的磁盤空間的,如果允許用戶定義區大小,萬一定義大了,不是每次都能找到那麼大的連續空間,如果找不到,豈不是要整理碎片空間去騰出連續空間,浪費時間不是;如果區定義小了,新問題出現了,整個數據庫的數據太碎了,每個區也存不了幾個數據,但是爲了要找到這些區的位置,還需要維護大量的區信息,而且,一次性稍微讀取多一點的數據時,就可能會讀取多個區,區之間並不是連續的,所以磁盤IO時間增大。 因此,我想既然官方給出了 1M 的大小,想必是比較合理的。

一個區包含多個頁,每個頁默認大小爲 16 K,innodb_page_size 這個全局參數可以設置的。因此,默認情況下,1 個區包含 64 個頁。頁是連續的空間,至於頁大小的設置與性能的關係,我覺得頁的大小要合適,16K 是官方給出的默認值,並且我看過一篇性能比較文章,對比了 8K 和 16K 頁的性能,結論是相差不多,8K 頁對CPU造成的壓力要比 16K 頁的高0.5 ~ 1 倍,但是對於 select 語句,8K 頁具有更大的吞吐量。相對來說,16K 是一個比較好的選擇。 頁分爲很多類型:數據頁,undo頁,系統頁,事務數據頁,插入緩存位圖頁,插入緩存空閒列表頁,未壓縮的二進制大對象頁,壓縮的二進制大對象頁。

每個表空間文件都會有一個頭頁,這個頁用於存儲這個表空間裏所有的段、區、頁的信息,以方便管理。

一頁包含很多行,由於一頁的大小有限,因此一頁存儲的行數也有限。 每一行的結構又是什麼樣呢?如下圖,比較老的MySQL版本默認按照compact格式,變長字段長度列表:記錄每個列字段的長度,如果列字段不超過255個字節,就用1個字節表示長度,如果超過了,就用2個字節表示,因此最大不能超過65535字節的字段存在,另外,長度列表的順序和列的順序相反。null標誌位爲1個字節,表示是否有哪一列的數據爲null。記錄頭信息爲5字節,每一個bit都是有意義的,具體信息如下面的表格(黑白圖)。

       

新版本的數據庫默認使用的行格式是Dynamic,好處是對於大數據的存儲有了更加方便的管理,比如BLOB類型的存儲,在行中用20個字節的空間存儲一個指針,指向一個頁,這個頁存儲着BLOB類型的數據。

上述內容如有不正確的,歡迎指出,相互學習,不勝感激! 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章