# 快速拉起一臺MySQL 8.0Docker容器,生產切勿這樣拉取,需要把數據目錄都掛載出來,這里我們只不過是為了研究MySQL,所以就不掛載了。
docker run --name mysql-8.0.27 -p 3306:3306 -e MYSQL_ROOT_PASSword=123456 -d mysql:8.0.27
MySQL整體架構分為哪兩部分?
- Server層:大多數的核心服務功能、所有的內置函數等一些跨存儲引擎的功能
- 存儲引擎層:負責數據的存儲和讀取
MySQL的存儲引擎主要有哪幾種?
- InnoDB:MySQL 5.5.5版本以后是默認引擎
- MyISAM
- Memory
在create table的時候可以指定引擎類型(engine=InnoDB|MyISAM|Memory),不同存儲引擎的表數據存儲方式也不一致。
MySQL Server層主要包含哪些組件?
- 連接器
- 查詢緩存
- 分析器
- 優化器
- 執行器
連接器
連接器的作用是?
連接器負責和客戶端建立連接、獲取權限、維持和管理連接。
# 連接mysql
mysql -h 127.0.0.1 -P 3306 -u root
- 客戶端首先和連接器通過TCP握手建立連接
- 對用戶輸入的用戶名和密碼進行驗證
- 驗證失敗會返回ERROR 1045 (28000): Access denied for user 'test'@'172.17.0.1' (using password: YES)錯誤
- 驗證通過以后,連接器會到權限表里面查處用戶擁有的權限。之后連接里面的權限邏輯判斷。都依賴于此時讀到的權限
注意這里的權限的修改一定要使用grant語句,不要手動改表,因為grant語句可以刷新內存,權限會立即更新,但是如果手動改表,權限不會刷新內存,內存里面的權限依舊是舊的。
如果手動改表的話請記得一定要跟上flush privileges這個SQL語句刷新內存。
權限表在哪里?
- 全局權限:mysql.user表
- 數據庫層級:mysql.db表
- 表層級:mysql.tables_priv表
- 列層級:mysql.columns_priv表
連接建立長時間無活動,連接器會怎么處理?
連接在建立后,如果客戶端太長時間沒有活動,連接器會自動將它斷開,該時間由wait_timeout和interactive_timeout參數控制,默認都是8小時。
- wait_timeout:非交互式連接的空閑超時
- interactive_timeout:交互式連接的空閑超時(程序連接MySQL Server為交互連接)
這兩個參數盡量設置為一樣的值。連接在被斷開以后,客戶端再次發送請求的話,會收到以下響應:
ERROR 4031 (HY000): The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior.
什么是長連接?
長連接是指連接建立成功以后,如果客戶端持續有請求就一直使用該連接,短連接每次執行完很少查詢就會斷開連接,下次需要重新建立。
數據庫為什么連接使用長連接?
連接建立過程相對復雜耗時,因此在使用過程中盡量減少連接的建立次數,使用長連接。
長連接的弊端是?
MySQL內存增長快速。
因為MySQL在執行過程中臨時使用的內存時管理在連接對象里面的,這些資源需要在斷開連接的時候才可以釋放。如果長連接累積下來會導致內存占用太大被系統強行殺掉。
如何解決長連接的弊端?
- 定時斷開長連接:使用一段時間或者程序判斷執行一個占用內存的大查詢后斷開連接,之后再重連
- mysql_reset_connection:在每次執行較大的操作后,執行mysql_reset_connection來重新初始化連接資源。該過程不需要重連,只是將連接恢復到剛創建完時的狀態。
mysql_reset_connection是為各個編程語言提供的API,不是SQL語句。
查詢緩存
MySQL獲得查詢請求后,會先查詢緩存,如果緩存中有直接返回,否則往下執行。
緩存中的key是查詢的語句,value是結果。
對表上的更新,會讓該表所有的緩存全部失效。
大多數情況下不建議使用緩存,緩存的弊遠遠大于利。MySQL8.0以后直接把查詢緩存的功能進行了移除。
分析器
MySQL Server在拿到SQL語句以后,需要知道這條語句干什么。
select id from test;
- 分析器做詞法分析:需要把一長串字符串進行識別,比如上述語句需要將select識別出來,這是一個查詢語句;test是表名,id是列名
- 詞法分析完成以后會做語法分析,語法分析器會根據語法規則判斷該SQL語句是否合法
這里還會對查的列和表是否存在做校驗(語義分析)。
優化器
在經過分析器以后,MySQL Server已經知道想要干啥,但是怎么干,如何干才能更快,此時就需要借助優化器了。
優化器會在有多個索引時決定使用哪個索引,或者有多表關聯時決定各個表的連接順序。
執行器
MySQL Server通過分析器知道要干啥,通過優化器知道怎么干,于是到達了執行器開始干。
但是在開始干之前需要檢查一下權限,如果權限校驗不通過就會返回沒有權限的錯誤,如下圖:
如果權限校驗通過,就打開表繼續執行。打開表會根據表的引擎定義去調用引擎提供的接口。
select * from test where id = 1;
假設上述表沒有索引,引擎是InnoDB,執行器會這樣操作:
- 調用InnoDB引擎接口獲取表的"第一行",判斷ID是否為1,如果不是則跳過,是就將這一行存入結果集
- 調用引擎接口取"下一行",重復第一步的邏輯判斷,直到取完表的"最后一行"
- 執行器將滿足條件的行的結果集返回給客戶端。
執行器調用一次,引擎內部可能會掃描多行。