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