MySQL進階必備知識(一):CS架構、配置文件、字符集等等

前文

  一直想抽時間總結下學習的知識,趁此給大家介紹下MySQL的進階知識,幫大夥兒梳理下關於MySQL那些零散的知識。如果關於MySQL你只知道mysql -uroot -proot登錄,並且知道一些ddl、dml語句,而對以下的問題不怎麼清楚,那這篇文章就值得一看

  • mysql服務端的啓動方式?
  • mysql的字符集?
  • mysql的索引是B+樹?具體是怎樣的?
  • mysql的記錄存放是怎麼存放的?
  • mysql的基本存放單位是記錄還是頁?他們之間是什麼關係?單鏈表or雙鏈表?
      以上等等,如果你想了解就接着往下看吧!本篇文章是基於混曰子的MySQL 是怎樣運行的:從根兒上理解 MySQL,這是本掘金的小冊,因爲我本人也買過很多極客時間的課程,可以說這本小冊絲毫不遜色於極客時間裏動則上百的課程,我本人看的是受益匪淺。在這裏也是良心推介,有興趣的朋友可以去購買閱讀。本篇大多數內容是基於小冊的概括總結。

MySQL的CS架構

  CS架構顧名思義就是client & server架構,在看小冊之前,我對服務端的瞭解也非常少,因爲一般只要啓動一次,後續就不用再啓動了,用的最多的還是mysql -uroot -proot客戶端登錄。但實際上mysql分爲服務端和客戶端,服務端僅一個,而客戶端可以有多個,甚至每個shell都能算一個單獨的客戶端!而服務端也設置了默認的最大連接數,一般是151。並且服務端的啓動也是比較簡單的。
  我們知道,平常輸的mysql僅是添加到$PATH路徑下的絕對路徑,在開啓終端時由shell比如bash來讀取這些路徑,從而linux就能通過mysql這個指令找到對應的安裝目錄下mysql這個程序。
  ok,如果你忘了你的絕對路徑,通過linux的which mysql可以查看:

$ which mysql
$ /usr/local/mysql/bin/mysql

  那我的mysql安裝目錄就是/usr/local/mysql,在其bin目錄下除了mysql外,還有我們比較熟悉的mysqldump、mysqladmin、mysqlbinlog這些,另還有啓動服務端的mysqld、mysqld_safe,所以接下來介紹三種啓動方式:

  1. mysqld啓動:/usr/local/mysql/bin/mysqld 即可啓動
  2. mysqld_safe 啓動(推介):這是啓動腳本,在mysqld上再封裝了一個監控程序,當mysqld掛了的時候,可以幫忙重啓,直接調用啓動即可
  3. mysql.server:這也是啓動腳本,調用mysqld_safe啓動,啓動mysql.server start

  以上的啓動還是比較簡單的”裸啓動“,也就是沒指明以什麼方式啓動,比如socket?比如tcp/ip?,也沒指定額外的配置文件,而是用默認路徑下的配置文件,比如我們可以用–defaults-file來指定配置文件,有點類似於redis-server redis.conf的形式!
  ok,先簡單介紹客戶端和服務端的通信方式,這兩者都運行起來就是linux上的進程了,所以二者的通信即是進程間的通信,在linux上一般就是用兩種:tcpip和socket,關於這兩者區別,我們可以參考mysql官網的一段話:

A MySQL client on Unix can connect to the mysqld server in two different ways: By using a Unix socket file to connect through a file in the file system (default /tmp/mysql.sock), or by using TCP/IP, which connects through a port number. A Unix socket file connection is faster than TCP/IP, but can be used only when connecting to a server on the same computer. A Unix socket file is used if you don’t specify a host name or if you specify the special host name loc -alhost.

  可以看到二者的區別就是文中我標粗的,socket連接速度更快於tcpip,但是它僅適用於客戶端和服務端在同一臺主機上,而tcpip則可以通過制定-h -P這樣的ip端口形式實現跨主機的連接,所以平常用的最多的還是tcpip,但是socket瞭解一下也是非常有必要的。

MYSQL的連接過程

  mysql的連接過程可以說是非常重要的,明白了這個你就知道你發了一段sql語句,mysql怎麼給你返回一個結果。那一般是三個步驟:

  • 建立連接:每個客戶端與服務器連接,服務器都會安排一個線程,當客戶端斷開時,線程會複用;當連接失敗,比如密碼錯誤則拒絕連接
  • 解析與優化:sql語句到了服務端就會立馬執行嗎?不會,會先查詢緩存,然後進行語法解析,最後查詢優化,這一切的目的都是爲了最快地返回結果。但緩存因維護成本過高,在mysql8.0就會被移除了。
  • 存儲引擎:目前最通用的就是innodb和myisam了,區別就是:物理上如何表示記錄,怎麼從表中讀取數據返回給客戶端。
mysql的一些配置參數

  這裏簡單介紹下MYSQL的配置參數,比如之前說的–defaults-file指定對應的配置文件來啓動,如果不指定,mysqld默認會在以下路徑尋找:/etc/my.cnf、/etc/mysql/my.cnf、$MYSQL_HOME/my.cnf、~/my.cnf等等總共7個路徑,而指定–defaults-file就可以跳過這些路徑的尋找,直接匹配進入,另外通過–defaults-extra-file 指定額外的路徑。
  除了配置文件就是配置參數了,常見的比如

  • –skip-networking可以禁止tcpip登錄
  • –skip-grant-tables 跳過權限表即在忘了登錄密碼時可以這樣啓動服務器

  很多時候我們需要查看一些參數的配置,mysql提供了幾個有用的語句,我們知道關於show語句,常見的就是show databases、show tables;那除了這兩個,以下的這幾個你也需要知道:
  • show variables:查看配置參數,我的mysql是453個,要查看具體的通過like來實現,比如show variables like “max_connections”/“query_cache_size”,前者表示查看最大連接數,後者表示查看緩存的大小。
  • show status:查看當前的運行狀態,狀態變量相對查看的比較少,因爲這些都是系統運行時服務端產生的一些狀態,無法修改,比如查看當前的連接數:show status like “Threads_connected”
  • show engines:查看當前版本都支持哪些引擎,以及默認的存儲殷勤是哪個

  關於系統變量即show variables裏面的參數設定,前面講過mysql的CS架構,一個服務端對應多個客戶端,就像HTTP一樣,http裏維護了session這樣的一個會話參數來記錄每個用戶的狀態,所以MySQL裏相應的也有session這樣的會話參數。MySQL服務端啓動時默認以global variables啓動的,每個客戶端連接上去後匹配單獨的線程,此時也匹配單獨的session variables(初始等同於global),隨後用戶set variables設置這些配置參數時都是默認在session會話裏,而如果想對所有的用戶都生效,則要認爲指定global,比如set global 變量名=值。

MySQL的字符集和比較規則

  字符集無論是哪門語言還是哪種數據庫都是必備的,而講起來相對篇幅也是比較大,這裏就介紹最爲重要的幾點。我們知道,計算機是基於二進制來交互的,所以一般輸入的字符就需要轉換爲字節,再轉換爲8個bit成爲計算機可以識別的內容。那字符要轉換爲1個字節還是2個字節?要怎麼轉換?這之間的規則就是由人定的,比如:

  • ASCII:定義了128個數,1個字符對應1個字節,包含空格、標點符號、數字、大小寫字母
  • latin1:在ASCII上擴充了128個西歐字符,也是1個字符對應1個字節
  • GBK:在ascii上擴充了中文、俄語等,ascii的對應1個字節,其他的2個字節
  • utf8:編碼一個字符對應1-4個字節,和utf16、utf32都屬於Unicode

  MySQL裏utf8和utfmb4很多人還是分的不清楚,簡單來講,utf8即是utf8mb3的縮寫,表示1-3個字節,utfmb4表示1-4個字節,這兩者最大的區別是utf8mb4包含的內容要更多,比如一些emoji在utf8就無法顯示,在utf8mb4就能顯示!

  比較規則也是非常重要的內容,MySQL裏經常需要排序,那這些排序針對字符串是怎麼比較的呢?一般我們都是用其默認的,但有時我們要按照特定的規則排序,那我們就必須瞭解這塊的內容,比如現在一般大小寫是忽略的,那如果你想要區分大小寫排序,就需要修改比較規則。
  查看字符集是show charset,就可以看到當前支持的字符集,以及默認的比較規則,掃過去可以看到default collation都是以ci結尾的,ci即case insensitive表示大小寫不敏感,而如果要修改區分大小寫,就改成cs(case sensitive)即可。
在這裏插入圖片描述
  關於比較規則可以通過show collation查看所有的比較規則,這邊就不多說了。現在講下比較規則和字符集的一一匹配關係,當僅修改字符集(charset)時,比如從utf8->gbk,則對應的collation會由MySQL幫忙修改,反之亦然!

MySQL字符集中的轉換

  在使用MySQL的過程中,經常會出現編碼錯誤,有時候在一臺機器上是正常的,但是遷到另一臺機器上又報編碼錯誤,搞得很心煩!所以要解決這個問題,就必須瞭解MySQL字符集中的轉換!
  首先我們需要了解三個參數:

  1. character_set_client —>服務端認爲客戶端的字符集
  2. character_set_connection—>連接的字符集
  3. character_set_results—>返回結果的字符集

  以上說明了這三個參數的作用,他們的關係是:當客戶端請求服務端的時候,服務端認爲客戶端是以set_client所設置的編碼發送的,但客戶端默認是以操作系統發送的,所以當操作系統的和set_client的不同,就會報錯!比如windows系統的默認是gbk,如果設置的是utf8,則報編碼異常,因爲我用的是mac,默認是utf8,所以是正確的。我們接着說,當客戶端的內容成功被解碼後,服務器還需要通過set_connection進行一次編碼在內部操作,然後再對應的解碼,最後用set_results編碼返回給客戶端!所以這三者把服務器的編碼解碼相對弄複雜了,但是如果你是類unix系統,就無須考慮太多,三個都設置成utf8即可!MySQL還貼心的給了一行代碼一口氣設置三個:

SET NAMES 字符集名; #比如set names utf8;

  除了以上的三個參數,實際上MySQL還提供了以下的參數,通過命令:

show variables like "character_set%";

在這裏插入圖片描述
  可以看到除了filesystem是binary,其他的都是utf8,這是因爲都是我設置的,爲了保持編碼一致!所以如果出現編碼錯誤了,可以查看下這些參數是否一致?亦或是是否和操作系統的一致!
  最後不得不說的是字符集和比較規則的粒度可以從列->數據表->數據庫->服務器四個級別!這意味着我們可以一張表不同的列具有不同的字符集!可以說非常人性化了!感興趣的可以自己瞭解下對應的SQL語句來設置。

總結

  考慮到篇幅原因,本篇就介紹到這裏,下一篇會繼續介紹記錄格式、索引等等!好了,多謝觀看~

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