天天看點

MySQL是怎樣運作的

根據我以往的經驗,MySQL會啟動一個服務,我們可以通過“用戶端”連結到服務,進行對資料庫的操作。

是以,它的執行步驟通常是這樣的:

啟動MySQL伺服器程式

啟動MySQL用戶端程式,連接配接到伺服器程式

在用戶端程式輸入指令語句,并将其作為請求(Http請求???)發送給伺服器程式。伺服器程式在收到這些請求後,根據請求的内容來操作具體的資料,并将結果傳回給用戶端。

代表MySQL伺服器程式的程序稱為MySQL資料庫執行個體

初次啟動需要安裝,使用<code>mysqld --initialize-insecure</code>,使用<code>console</code>選項可以将安裝結果列印在控制台上

如果需要安裝服務,使用<code>mysqld --install</code>即可

在指令行中指定啟動選項的格式如下:

其中要注意的是啟動選項全稱前要使用<code>--</code>,單詞連接配接可以使用<code>-</code>或者<code>_</code>,且單詞和值之間不要有空格

mysql程式在啟動時會在多個路徑下尋找配置檔案,不過我們一般隻需要在<code>basedir</code>,也就是mysql安裝目錄下防止一份名為<code>my.ini</code>或者<code>my.cnf</code>的配置檔案即可

……

由于4位元組字元實在不常用(emoji等),是以MySQL預設了兩個容易混淆的概念:

utf8mb3:精簡的UTF-8字元集,隻能表示1~3位元組的字元,在MySQL中,utf-8==utf8mb3

utf8mb4:完整的UTF-8字元集能表示1~4位元組的字元

是以,如果要在MySQL(版本低于8.0)中存儲emoji,要修改MySQL字元集;版本大于8.0後,已經對字元集進行了優化,可以utf-8得以真正地等于utf-8,并且作為資料庫的預設字元集出現

通過在控制台輸入<code>show charset</code>即可檢視目前支援的字元集,可以看到這些字元集都為小寫形式出現,值得我們注意的就是最後一列的Maxlen,即最大字元長度

使用<code>show collation</code>指令檢視比較規則,但所有字元集的比較規則太多,我們隻檢視utf8的,<code>show collation where charset like 'utf8';</code>,結果如下,期中Default為Yes的就是該字元集預設的比較規則

這其中的規律是:

“utf8”字首:表示規則所屬的字元集

緊跟字首:表示規則所應用的語言

“ci”字尾:表示是否區分語言中的重音、大小寫等

字尾

全稱

含義

<code>_ai</code>

accent insensitive

不區分重音

<code>_as</code>

accent sensitive

區分重音

<code>_ci</code>

case insensitive

不區分大小寫

<code>_cs</code>

case sensitive

區分大小寫

<code>_bin</code>

binary

以二進制方式比較

示例: <code>utf8_spanish_ci</code> 表示以西班牙語比較,且不區分大小寫

MySQL存在4個級别的字元集和比較規則,分别是伺服器級别、資料庫級别、表級别、列級别

1 伺服器級别

MySQL通過兩個系統變量來管理伺服器級别的字元集和比較規則,通過<code>show variables like 'character_set_server\collation_server';</code>檢視這兩個變量

系統标量

描述

<code>character_set_server</code>

伺服器級别的字元集

<code>collation_server</code>

伺服器級别的字元集比較規則

可以通過在ini配置檔案中配置這兩個變量來制定具體的字元集和規則,

2 資料庫級别

在建立和修改資料庫時就可以制定該資料庫的字元集和比較規則:

在建立完資料并選擇中資料庫後,可以使用

來檢視這兩個變量,但是,我們隻能通過這兩個變量來檢視資料庫級别的字元集和比較規則,而不能通過這兩個變量進行修改

3 表級别

指定方式相同:

既然是表的屬性,自然可以通過<code>alter</code>關鍵字進行修改

4 列級别

制定方式:

修改方式:

要注意的是,在修改字元集和比較規則的時候,如果兩個字元集的字元不能互相表示就會引起錯誤,比如将ASCⅡ的轉換成utf8

5 僅修改字元集或者比較規則

隻修改字元集,比較規則會自動變成字元集預設的比較規則

隻修改比較規則,字元集會變成與之對應的

了解字元集和比較規則後,我們就能夠清楚地判斷一條記錄的實際大小了

對于同一個字元,如果編碼和解碼使用的字元集不一樣就會産生不必要的誤解,是以我們需要一套字元集轉換的系統:即按照utf8字元集對0xE68891進行解碼,随後按照GBK字元集編碼成0XCED2,這樣就完成了漢字“我”跨字元集的轉換。在MySQL中,這樣的轉換時常發生

MySQL用戶端種類繁多,預設的用戶端(bin下的mysql程式)使用的字元集和作業系統一緻,要檢視作業系統的字元集:

UNIX:LC_ALL、LC_CTYPE、LANG這三個環境變量依次決定了系統的字元集

Windows:通過使用指令<code>chcp</code>檢視

在Windows下,通過在ini或者在啟動指令中指定<code>default-character-set</code>的值來修改用戶端預設字元集

本質上說,伺服器接收到的請求就是一個位元組序列,而它認為這個位元組序列的編碼就是<code>character_set_client</code>對應的值(每個用戶端有單獨的值),如果改變這個值,将會産生意料之中的錯誤:

伺服器使用<code>character_set_client</code>指定的字元集來解析位元組序列,但真正處理它們還需要将解析後的位元組序列轉換成由<code>character_set_connection</code>指定的編碼後進行。為什麼要多加轉換的一步呢?

在上面這個例子中,伺服器在接收到請求後無法判斷這兩個字元所處的字元集和比較規則,此時<code>character_set_connection</code>就發揮了作用,上述情況是字元集制定為utf8的情況,下面這種就不一樣了:

可以看到,再将連接配接字元集和比較規則改變後,比較結果就發生了變化。那麼問題又來了,用戶端不是有一套字元集和比較規則嘛,直接用用戶端的不就行了!可有些時候,你會拿字元串和表中的資料進行比較,這時候就需要連接配接字元集來進行統一了:

表格中的資料是utf8編碼的,而用戶端發送的請求位元組序列确實按照<code>character_set_client</code>指定的,若這個變量的值為gbk,那麼這兩個字元比較起來就麻煩了,是以,需要統一地将他們轉換成優先級更高的字元(在這裡就是表中的utf8)

在讀取到資料結果後,伺服器會根據character_set_results系統變量對應的字元編集進行轉換後傳回給用戶端

用戶端會使用用戶端預設的字元集來解釋這個由伺服器傳回的位元組序列,以下的例子中将傳回結果字元集設定成了gbk,而用戶端字元集為utf8,于是就産生了亂碼!是以,暫且來看,client和result要保持一緻

另外,可以通過<code>set names charset_name;</code>來一鍵配置這三個變量,還可以在ini檔案中配置<code>default-character-set</code>來配置這些變量