第一節:認識MySQL
-----------------------------------------------------------
客戶端/服務器架構
MySQL它的服務器程序直接和我們存儲的數據打交道,然后可以有好多客戶端程序連接到這個服務器程序,發送增刪改查的請求,然后服務器就響應這些請求,從而操作它維護的數據。
每個客戶端都需要提供用戶名密碼才能登錄,登錄之后才能給服務器發請求來操作某些數據。
我們的MySQL服務器程序和客戶端程序本質上都算是計算機上的一個進程,這個代表着MySQL服務器程序的進程也被稱為MySQL數據庫實例,簡稱數據庫實例。
每個進程都有一個唯一的編號,稱為進程ID,英文名叫PID,這個編號是在我們啟動程序的時候由操作系統隨機分配的,操作系統會保證在某一時刻同一台機器上的進程號不重復。比如你打開了計算機中的QQ程序,那么操作系統會為它分配一個唯一的進程號,如果你把這個程序關掉了,那操作系統就會把這個進程號回收,之后可能會重新分配給別的進程。當我們下一次再啟動 QQ程序的時候分配的就可能是另一個編號。
每個進程都有一個名稱,這個名稱是編寫程序的人自己定義的,比如我們啟動的MySQL服務器進程的默認名稱為mysqld, 而我們常用的MySQL客戶端進程的默認名稱為mysql。
-----------------------------------------------------------
啟動MySQL服務器程序
在類UNIX系統中用來啟動MySQL服務器程序的可執行文件有很多,大多在MySQL安裝目錄的bin目錄下:
mysqld這個可執行文件就代表着MySQL服務器程序,運行這個可執行文件就可以直接啟動一個服務器進程。但這個命令不常用,我們繼續往下看更牛逼的啟動命令。
mysqld_safe是一個啟動腳本,它會間接的調用mysqld,而且還順便啟動了另外一個監控進程,這個監控進程在服務器進程掛了的時候,可以幫助重啟它。另外,使用mysqld_safe啟動服務器程序時,它會將服務器程序的出錯信息和其他診斷信息重定向到某個文件中,產生出錯日志,這樣可以方便我們找出發生錯誤的原因。
mysql.server也是一個啟動腳本,它會間接的調用mysqld_safe,在調用mysql.server時在后邊指定start參數就可以啟動服務器程序了,就像這樣:mysql.server start
需要注意的是,這個 mysql.server 文件其實是一個鏈接文件,它的實際文件是 ../support-files/mysql.server
其實我們一台計算機上也可以運行多個服務器實例,也就是運行多個MySQL服務器進程。mysql_multi可執行文件可以對每一個服務器進程的啟動或停止進行監控。--具體怎么使用這個命令,可以查一下。
Windows下的服務開啟與關閉:net start/stop MySQL。
-----------------------------------------------------------
啟動MySQL客戶端程序
退出客戶端:quit|exit|\q
bin目錄下有許多客戶端程序,比方說mysqladmin、mysqldump、mysqlcheck等等等等(好多呢,就不一一列舉了)。這里我們重點要關注的是可執行文件mysql,通過這個可執行文件可以讓我們和服務器程序進程交互,也就是發送請求,接收服務器的處理結果。
mysql -h主機名 -u用戶名 -p密碼
如果你願意,你可以多打開幾個黑框框,每個黑框框都使用mysql -hlocalhost -uroot -p123456來運行多個客戶端程序,每個客戶端程序都是互不影響的。如果你有多個電腦,也可以試試把它們用局域網連起來,在一個電腦上啟動MySQL服務器程序,在另一個電腦上執行mysql命令時使用IP地址作為主機名來連接到服務器。
連接注意事項:
最好不要在一行命令中輸入密碼。
如果你非要在一行命令中顯式的把密碼輸出來,那-p和密碼值之間不能有空白字符(其他參數名之間可以有空白字符)
mysql的各個參數的擺放順序沒有硬性規定
如果你的服務器和客戶端安裝在同一台機器上,-h參數可以省略
如果你使用的是類UNIX系統,並且省略-u參數后,會把你登陸操作系統的用戶名當作MySQL的用戶名去處理
對於Windows系統來說,默認的用戶名是ODBC,你可以通過設置環境變量USER來添加一個默認用戶名
-----------------------------------------------------------
客戶端與服務器連接的過程
運行着的服務器程序和客戶端程序本質上都是計算機上的一個進程,所以客戶端進程向服務器進程發送請求並得到回復的過程本質上是一個進程間通信的過程!MySQL支持下邊三種客戶端進程和服務器進程的通信方式。
TCP/IP
真實環境中,數據庫服務器進程和客戶端進程可能運行在不同的主機中,它們之間必須通過網絡來進行通訊。
MySQL采用TCP作為服務器和客戶端之間的網絡通信協議。在網絡環境下,每台計算機都有一個唯一的IP地址,如果某個進程有需要采用TCP協議進行網絡通信方面的需求,可以向操作系統申請一個端口號,這是一個整數值,它的取值范圍是0~65535。這樣在網絡中的其他進程就可以通過IP地址 + 端口號的方式來與這個進程連接,這樣進程之間就可以通過網絡進行通信了。
如果3306端口號已經被別的進程占用了或者我們單純的想自定義該數據庫實例監聽的端口號,那我們可以在啟動服務器程序的命令行里添加-P參數來明確指定一下端口號。
服務端可以這么啟動:mysqld -P3307
客戶端可以這樣啟動:mysql -h127.0.0.1 -uroot -P3307 -p
-----------------------------------------------------------
命名管道和共享內存
1.使用命名管道來進行進程間通信
需要在啟動服務器程序的命令中加上--enable-named-pipe參數,然后在啟動客戶端程序的命令中加入--pipe或者--protocol=pipe參數。
2.使用共享內存來進行進程間通信
需要在啟動服務器程序的命令中加上--shared-memory參數,在成功啟動服務器后,共享內存便成為本地客戶端程序的默認連接方式,不過我們也可以在啟動客戶端程序的命令中加入--protocol=memory參數來顯式的指定使用共享內存進行通信。
需要注意的是,使用共享內存的方式進行通信的服務器進程和客戶端進程必須在同一台Windows主機中。
Unix域套接字文件
如果我們的服務器進程和客戶端進程都運行在同一台操作系統為類Unix的機器上的話,我們可以使用Unix域套接字文件來進行進程間通信。
-----------------------------------------------------------
服務器處理客戶端請求
不論客戶端進程和服務器進程是采用哪種方式進行通信,最后實現的效果都是:客戶端進程向服務器進程發送一段文本(MySQL語句),服務器進程處理后再向客戶端進程發送一段文本(處理結果)。
服務器程序處理來自客戶端的查詢請求大致需要經過三個部分,分別是連接管理、解析與優化、存儲引擎。
1.連接管理
每當有一個客戶端進程連接到服務器進程時,服務器進程都會創建一個線程來專門處理與這個客戶端的交互,當該客戶端退出時會與服務器斷開連接,服務器並不會立即把與該客戶端交互的線程銷毀掉,而是把它緩存起來,在另一個新的客戶端再進行連接時,把這個緩存的線程分配給該新客戶端。這樣就起到了不頻繁創建和銷毀線程的效果,從而節省開銷。從這一點大家也能看出,MySQL服務器會為每一個連接進來的客戶端分配一個線程,但是線程分配的太多了會嚴重影響系統性能,所以我們也需要限制一下可以同時連接到服務器的客戶端數量。
在客戶端程序發起連接的時候,需要攜帶主機信息、用戶名、密碼,服務器程序會對客戶端程序提供的這些信息進行認證,如果認證失敗,服務器程序會拒絕連接。另外,如果客戶端程序和服務器程序不運行在一台計算機上,我們還可以采用使用了SSL(安全套接字)的網絡連接進行通信,來保證數據傳輸的安全性。
2.解析與優化
其中的幾個比較重要的部分分別是查詢緩存、語法解析和查詢優化
查詢緩存
雖然查詢緩存有時可以提升系統性能,但也不得不因維護這塊緩存而造成一些開銷,比如每次都要去查詢緩存中檢索,查詢請求處理完需要更新查詢緩存,維護該查詢緩存對應的內存區域。從MySQL 5.7.20開始,不推薦使用查詢緩存,並在MySQL 8.0中刪除。
語法解析
客戶端程序發送過來的請求只是一段文本而已,所以MySQL服務器程序首先要對這段文本做分析,判斷請求的語法是否正確,然后從文本中將要查詢的表、各種查詢條件都提取出來放到MySQL服務器內部使用的一些數據結構上來。
查詢優化
我們寫的MySQL語句執行起來效率可能並不是很高,MySQL的優化程序會對我們的語句做一些優化,如外連接轉換為內連接、表達式簡化、子查詢轉為連接吧啦吧啦的一堆東西。優化的結果就是生成一個執行計划,這個執行計划表明了應該使用哪些索引進行查詢,表之間的連接順序是啥樣的。我們可以使用EXPLAIN語句來查看某個語句的執行計划,關於查詢優化這部分的詳細內容我們后邊會仔細嘮叨,現在你只需要知道在MySQL服務器程序處理請求的過程中有這么一個步驟就好了。
3.存儲引擎
MySQL服務器把數據的存儲和提取操作都封裝到了一個叫存儲引擎的模塊里。我們知道表是由一行一行的記錄組成的,但這只是一個邏輯上的概念,物理上如何表示記錄,怎么從表中讀取數據,怎么把數據寫入具體的物理存儲器上,這都是存儲引擎負責的事情。為了實現不同的功能,MySQL提供了各式各樣的存儲引擎,不同存儲引擎管理的表具體的存儲結構可能不同,采用的存取算法也可能不同。
為什么叫`引擎`呢?因為這個名字更拉風~ 其實這個存儲引擎以前叫做`表處理器`,后來可能人們覺得太土,就改成了`存儲引擎`的叫法,它的功能就是接收上層傳下來的指令,然后對表中的數據進行提取或寫入操作。
為了管理方便,人們把連接管理、查詢緩存、語法解析、查詢優化這些並不涉及真實數據存儲的功能划分為MySQL server的功能,把真實存取數據的功能划分為存儲引擎的功能。各種不同的存儲引擎向上邊的MySQL server層提供統一的調用接口(也就是存儲引擎API),包含了幾十個底層函數,像"讀取索引第一條內容"、"讀取索引下一條內容"、"插入記錄"等等。
所以在MySQL server完成了查詢優化后,只需按照生成的執行計划調用底層存儲引擎提供的API,獲取到數據后返回給客戶端就好了。
-----------------------------------------------------------
常用的存儲引擎
這么多我們怎么挑啊,哈哈,你多慮了,其實我們最常用的就是InnoDB和MyISAM,有時會提一下Memory。其中InnoDB是MySQL默認的存儲引擎。
查看當前服務器程序支持的存儲引擎:SHOW ENGINES;
Support列表示該存儲引擎是否可用,DEFAULT值代表是當前服務器程序的默認存儲引擎。Comment列是對存儲引擎的一個描述,英文的,將就着看吧。Transactions列代表該存儲引擎是否支持事務處理。XA列代表着該存儲引擎是否支持分布式事務。Savepoints代表着該存儲引擎是否支持部分事務回滾。
設置表的存儲引擎
我們前邊說過,存儲引擎是負責對表中的數據進行提取和寫入工作的,我們可以為不同的表設置不同的存儲引擎,也就是說不同的表可以有不同的物理存儲結構,不同的提取和寫入方式。
1.創建表時指定存儲引擎
我們之前創建表的語句都沒有指定表的存儲引擎,那就會使用默認的存儲引擎InnoDB(當然這個默認的存儲引擎也是可以修改的,我們在后邊的章節中再說怎么改)
2.修改表的存儲引擎
如果表已經建好了,我們也可以使用下邊這個語句來修改表的存儲引擎:
ALTER TABLE 表名 ENGINE = 存儲引擎名稱;