执行计划 分析一条sql语句的效率 mysql_MySQL中一条SQL语句的执行过程
MySQL中一條SQL語句的執行過程
發布時間:2018-11-24 18:35,
瀏覽次數:390
, 標簽:
MySQL
SQL
查詢語句的執行順序:
1.客戶端通過TCP連接發送連接請求到mysql連接器,連接器會對該請求進行權限驗證及連接資源分配(max_connections,8小時超時)
2.建立連接后客戶端發送一條語句,mysql收到該語句后,通過命令分發器判斷其是否是一條select語句,如果是,在開啟查詢緩存的情況下,先在查詢緩存中查找該SQL是否完全匹配,如果完全匹配,驗證當前用戶是否具備查詢權限,如果權限驗證通過,直接返回結果集給客戶端,該查詢也就完成了。如果不匹配繼續向下執行。(
注意:此步并不做詞法及語法分析,也就是用不到分析器,這塊原來我也很疑惑,如果不做分析mysql怎么知道我要查什么?解釋如下:{MySQL將緩存存放在一個引用表中,通過一個哈希值引用,這個哈希值包括了以下因素,即查詢本身、當前要查詢的數據庫、客戶端協議的版本等一些其他可能影響返回結果的信息。
當判斷緩存是否命中時,MySQL不會進行解析查詢語句,而是直接使用SQL語句和客戶端發送過來的其他原始信息。所以,任何字符上的不同,例如空格、注解等都會導致緩存的不命中。}
其實說白了大概就是拿著你的SQL和原始緩存的SQL比對)
3.如果在查詢緩存中未匹配成功,則將語句交給分析器作語法分析,MySQL需要知道到底要查哪些東西,如果語法不對,就會返回語法錯誤中斷查詢。
4.分析器的工作完成后,將語句傳遞給預處理器,檢查數據表和數據列是否存在,解析別名看是否存在歧義等
5.語句解析完成后,MySQL就知道要查什么了,之后會將語句傳遞給優化器進行優化(通過索引選擇最快的查找方式),并生成執行計劃。
6.之后交給執行器去具體執行該語句,在執行之前,會先檢查該用戶是否具有查詢權限,如果有,繼續執行該語句。執行器開始執行后,會逐漸將數據保存到結果集中,同時會逐步將數據緩存到查詢緩存中,最終將結果集返回給客戶端。(緩存到查詢緩存受到幾個參數的影響
1.query_cache_type 是否打開查詢緩存,默認為OFF? 2.query_cache_size:查詢緩存使用的總內存空間,默認值為1M
3.query_cache_limit
對于大于該值的結果集不會被緩存,默認值1M,在8.0版本后該參數被移除了)(如果該SQL執行過程中超過了慢查詢閥值,該SQL會被記錄到慢查詢日志中)
#######################################################
一條更新語句的執行順序:
1.客戶端通過TCP連接發送連接請求到mysql連接器,連接器會對該請求進行權限驗證及連接資源分配(max_connections,8小時超時)
2.建立連接后客戶端發送一條語句,mysql收到該語句后,通過命令分發器判斷其是否是一條更新語句,如果是,則直接發送給分析器做語法分析。
3.分析器階段,MySQL需要知道到底要查哪些東西,如果語法不對,就會返回語法錯誤中斷查詢
4.分析器的工作完成后,將語句傳遞給預處理器,檢查數據表和數據列是否存在,解析別名看是否存在歧義等
5.語句解析完成后,MySQL就知道要查什么了,之后會將語句傳遞給優化器進行優化(通過索引選擇最快的查找方式),并生成執行計劃。
6.執行器根據生成的執行計劃去open
table,此時會先去查看該表上是否有元數據(MDL)排他鎖(如果有元數據共享鎖則無影響),如果有元數據排他鎖,則事物被阻塞,進入等待狀態(時間由lock_wait_timeout決定,默認是一年。。。。),等元數據鎖被釋放,繼續執行。如果無元數據鎖或者是有元數據共享鎖,則該事務在表上加元數據共享鎖(因為元數據共享讀鎖之間是不沖突的,如果表上有元數據共享鎖,我們執行alter
table這樣的DDL語句時,會進入等待狀態,因為DDL語句需要在表上加元數據排他鎖)
7.進入引擎層(默認innodb),去innodb_buffer_pool里面的data dictionary得到表得相關信息
8.根據表信息去innodb_buffer_pool里面的lock
info查看是否有相關的鎖信息,如果有則等待(因為要加排它鎖),如果沒有則加排它鎖,更新lock info。
9.取讀取相關數據頁到innodb_buffer_pool中(如果數據頁本身就在緩存中,則不用從硬盤讀取)
10.將頁中的原始數據(快照)保存到undo log buffer中(undo log buffer會以相關參數定義的規則進行刷盤操作寫入到undo
tablespace中)
11.在innodb_buffer_pool中將相關頁面更新,該頁變成臟頁(臟頁會以相關參數定義的規則進行刷盤操作寫入所屬表空間中)
12.頁面修改完成后,會把修改后的物理頁面保存到redo log buffer中,(redo log
buffer會以相關參數定義的規則進行刷盤操作寫入到redo tablespace中)
13.如果開啟binlog,則更新數據的邏輯語句也會記錄在binlog_cache中(binlog會以相關參數定義的規則進行刷盤操作寫入到binlog
file 中)
14.如果該表上有二級索引并且本次操作會影響到二級索引,則會把相關的二級索引修改寫入到innodb_buffer_pool中的change
buffer里(change buffer 會以相關參數定義的規則進行刷盤操作寫入所屬表空間中)
15.前期的準備工作到此已經做完了,之后便是事務的commit或者rollback操作。一般情況下執行的是commit操作
16.執行commit操作后(mysql默認開啟自動提交,如果手動開始事務begin,則需要顯示提交commit),由于要保證redolog與binlog的一致性,redolog采用2階段提交方式。
17.將undo log buffer及redo log
buffer刷盤(innodb_flush_log_at_trx_commit=1),并將該事務的redolog標記為prepare狀態。
18.將binlog_cache數據刷盤(sync_binlog=1)
19.如果開啟了主從結構,此時會將binlog_cache中的信息通過io線程發送給從機,如果開啟了半同步復制則需要等待從機落盤(relay
log)并反饋。如果是異步復制則無需等待(默認是異步復制)
20.待binlog落盤完成,再將redolog中該事務信息標記為commit,釋放相關鎖資源。此時一個更新事務的操作已經完成,返回給客戶端成功更新提示。
21.標記undolog中該事務修改頁的原始快照信息為delete,當無其他事務引用該原始數據時(MVCC),再將其刪除
22.如果此時觸發了臟頁刷盤操作,會先將臟頁寫入到double write
buffer中(防止寫入過程中出現斷頁,因為mysql頁面默認為16K,linux操作系統最大為4K,如果寫了8K時系統掛了,這個數據頁將不完整,標記為損壞)然后再寫到期所在表空間的相應位置。
總結
以上是生活随笔為你收集整理的执行计划 分析一条sql语句的效率 mysql_MySQL中一条SQL语句的执行过程的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: DistCp迁移Hive数据过程中源集群
 - 下一篇: 逻辑回归原理