MySQL:sending data狀態包含了什麼
MySQL:sending data狀態包含了什麼
一、問題由來
這是一個朋友問我的(@成都--麥澀可),原問題如下:
-
資料庫傳送資料給客戶端這個時間算是sql的執行時間嘛?
要解決問題我們需要知道MySQL何時將資料傳輸給了客戶端,既然是要傳輸實際的資料給客戶端那麼肯定是select語句了,同時我們要明白一個正常select執行到底要經歷哪些階段。
二、一個簡單SELECT語句經歷的階段
2392 T@10: | | | | | THD::enter_stage: 'checking permissions' /root/mysql5.7.14/percona-server-5.7.14-7/sql/auth/sql_authorization.cc:843 2404 T@10: | | | | | | THD::enter_stage: 'Opening tables' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_base.cc:5719 2512 T@10: | | | | | THD::enter_stage: 'init' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_select.cc:121 2681 T@10: | | | | | | | THD::enter_stage: 'System lock' /root/mysql5.7.14/percona-server-5.7.14-7/sql/lock.cc:321 2772 T@10: | | | | | | | THD::enter_stage: 'optimizing' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_optimizer.cc:151 2865 T@10: | | | | | | | THD::enter_stage: 'statistics' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_optimizer.cc:386 3329 T@10: | | | | | | | THD::enter_stage: 'preparing' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_optimizer.cc:494 3466 T@10: | | | | | | THD::enter_stage: 'executing' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_executor.cc:119 3474 T@10: | | | | | | THD::enter_stage: 'Sending data' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_executor.cc:195 3668 T@10: | | | | | THD::enter_stage: 'end' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_select.cc:199 3685 T@10: | | | | THD::enter_stage: 'query end' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_parse.cc:5174 3754 T@10: | | | | THD::enter_stage: 'closing tables' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_parse.cc:5252 3882 T@10: | | | THD::enter_stage: 'freeing items' /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_parse.cc:5855
實際上整個階段都算到了語句的實際消耗時間之中的,但是慢查詢記錄的是:
-
實際執行時間 = (freeing items 末端的時間) 實際消耗時間 - (System lock末端的時間 )比如MDL LOCK等待時間 - (Innodb層鎖定的時間)行鎖等待消耗時間
關於慢查詢的詳細情況可以參考我的一篇文章,這裡不再重述。
MySQL慢查詢記錄原理和內容解析
三、什麼是Sending data狀態
實際上這個狀態是select語句才會有的,如果是DML則不同但是都有等同的階段如下:
-
select:Sending data
-
insert語句:Update
-
delete/update:Updating
這個階段非常的巨大,它至少包含了:
-
Innodb 層資料的定位返回給MySQL 層
-
Innodb 層資料的查詢返回給MySQL 層
-
Innodb 層資料的修改(如果是MDL)
-
Innodb 層加鎖以及等待
-
等待進入Innodb層(innodb_thread_concurrency引數)
-
MySQL 層傳送資料給客戶端
可以看到基本所有和Innodb層打交道的過程都包裹在這個狀態下面,當然我只是列舉了我想到的一些,其實可能還有很多很多,這裡我也把 MySQL 層傳送資料給客戶端 包含在 Sending data的答案給出了,下面我們進行分析。
四、如何證明Sending data狀態包含了網路資料傳輸的時間
之前你可以參考一下我的文章
MySQL:Innodb Handler_read_*變數解釋
我們建立一個簡單的表如下,並且填充資料如下:
Create Table: CREATE TABLE `ty` ( `id` int(11) NOT NULL AUTO_INCREMENT, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idxa` (`a`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 mysql> select * from ty; +----+------+------+| id | a | b |+----+------+------+| 8 | 2 | 3 || 9 | 5 | 4 || 10 | 6 | 7 || 11 | 6 | 8 |+----+------+------+4 rows in set (4.14 sec)
我們執行如下語句:
mysql> desc select * from ty where a =6 and b=8; +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | ty | NULL | ref | idxa | idxa | 5 | const | 2 | 33.33 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+ mysql> select * from ty where a =6 and b=8; +----+------+------+| id | a | b |+----+------+------+| 11 | 6 | 8 |+----+------+------+1 row in set (7.22 sec)
注意:這裡的語句執行時間很長是因為我打了GDB斷點所以看起來很久而已
我做了語句的trace,這個語句大概需要如下步驟:
-
首先Innodb定位到索引
idxa
資料6所在位置這是初次定位呼叫函式ha_innobase::index_read,返回資料| 10 | 6 | 7 |給MySQL層,但是MySQL層過濾掉不符合條件 a =6 and b=8 不需要返回給客戶端。
1547 T@12: | | | | | | | | >handler::ha_index_read_map 1548 T@12: | | | | | | | | | >index_read (這裡進行初次訪問索引定位) 1552 T@12: | | | | | | | | | | >row_search_mvcc 1553 T@12: | | | | | | | | | | | >btr_cur_search_to_nth_level 1554 T@12: | | | | | | | | | | | <btr_cur_search_to_nth_level 2009 ... 1593 T@12: | | | | | | | | | | <row_search_mvcc 6070 1594 T@12: | | | | | | | | | <index_read 9179 1595 T@12: | | | | | | | | <handler::ha_index_read_map 3190 1596 T@12: | | | | | | | | >evaluate_join_record (這裡進入MySQL 層where條件判斷流程,不滿足不傳送) ... 1600 T@12: | | | | | | | | <evaluate_join_record 1701
-
定位完成後再次訪問索引
idxa
的下一條資料,Innodb直接讀取就好了呼叫函式ha_innobase::index_next_same,返回資料| 11 | 6 | 8 |給Mysql層,因為滿足條件 a =6 and b=8所以返回給客戶端
。
1601 T@12: | | | | | | | | >handler::ha_index_next_same(這裡就是順序訪問索引的下一行資料了) 1602 T@12: | | | | | | | | | >general_fetch 1603 T@12: | | | | | | | | | | >row_search_mvcc .... 1607 T@12: | | | | | | | | | | <row_search_mvcc 6070 1608 T@12: | | | | | | | | | <general_fetch 9487 1609 T@12: | | | | | | | | <handler::ha_index_next_same 3414 1610 T@12: | | | | | | | | >evaluate_join_record(這裡進入MySQL 層where條件判斷流程,滿足條件需要傳送) 1613 T@12: | | | | | | | | | >end_send 1614 T@12: | | | | | | | | | | >Query_result_send::send_data(這裡就是傳送資料給客戶端了,也就是透過網路傳送資料給客戶端了) 1615 T@12: | | | | | | | | | | | >send_result_set_row 1616 T@12: | | | | | | | | | | | <send_result_set_row 4967 1620 T@12: | | | | | | | | | | <Query_result_send::send_data 2915 1621 T@12: | | | | | | | | | | >Protocol_classic::end_row 1622 T@12: | | | | | | | | | | <Protocol_classic::end_row 1198 1625 T@12: | | | | | | | | | <end_send 2991 1626 T@12: | | | | | | | | <evaluate_join_record 1701
-
因為是非唯一索引因此需要再次訪問下一條資料來判斷已經讀取了所有a=6的資料,因此Innodb需要在讀取索引
idxa
的下一條資料呼叫函式ha_innobase::index_next_same。
1627 T@12: | | | | | | | | >handler::ha_index_next_same(這裡就是順序訪問索引的下一行資料了) 1628 T@12: | | | | | | | | | >general_fetch 1629 T@12: | | | | | | | | | | >row_search_mvcc ... 1639 T@12: | | | | | | | | | | <row_search_mvcc 6070 1640 T@12: | | | | | | | | | <general_fetch 9487 1641 T@12: | | | | | | | | <handler::ha_index_next_same 3414
所以總結整個流程一共經歷了一次索引定位,兩次索引順序讀取,一共讀取了三條資料,但是返回給MySQL層的只有前面兩條資料,透過MySQL層的過濾只傳送給了客戶端一條滿足條件的資料。
五、總結
很顯然資料返回給客戶端的時間包含在了整個語句的實際消耗時間中,同時包含在了慢查詢的實際執行時間(Query_time指標)中,它是在sending data狀態下完成的。
作者微信:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2215202/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL:關於RR模式下insert..selcet sending data狀態說明MySql模式
- 12、MySQL Case-show processlist 狀態一直處於Sending to clientMySqlclient
- MySQL Sending data導致查詢很慢的問題詳細分析MySql
- HTTP狀態程式碼是什麼?HTTP
- 什麼時候用有狀態session bean,什麼時候用無狀態session bean (轉)SessionBean
- MySQL查詢中Sending data佔用大量時間的問題處理MySql
- 什麼是HTTP 304狀態程式碼?HTTP
- session的狀態什麼時候是snipedSession
- http狀態碼是什麼,有什麼用,在哪裡檢視,分別代表什麼意思?HTTP
- steam雲狀態無法同步怎麼辦 steam雲狀態無法同步會有什麼影響
- vue麵包屑(vue動態路由多級巢狀麵包屑怎麼弄)Vue路由巢狀
- mysql 鎖狀態的一些狀態資訊記錄MySql
- 網站常用的狀態碼有什麼?網路安全技學習什麼網站
- 什麼是Spring Data?Spring
- MySQL 分析伺服器狀態MySql伺服器
- Python: 攜帶狀態的閉包Python
- 更改模型中的請求包狀態模型
- 【翻譯】What is State Machine Diagram(什麼是狀態機圖)?Mac
- MySQL執行緒狀態詳解MySql執行緒
- MySQL MHA 執行狀態監控MySql
- 獲取Mysql的狀態、變數MySql變數
- Mysql複製執行緒狀態MySql執行緒
- 檢測mysql狀態的指令碼MySql指令碼
- 什麼?你還不會用位運算來操作狀態?
- AndroidTips:selector的disable狀態為什麼無效?Android
- MySQL執行狀態監控(pt-mysql-summary)MySql
- 配置CACTI監控MySQL資料庫狀態(2)安裝cacti相關軟體包MySql資料庫
- "Spring 1.x無容器Session狀態支援"到底什麼意思?SpringSession
- 7. 監控MySQL主從狀態MySql
- Galera Cluster for MySQL監控狀態說明MySql
- 【MYSQL】state狀態converting HEAP to MyISAMMySql
- mysql較為重要的狀態變數MySql變數
- Python中什麼是閉包?閉包的好處是什麼?Python
- [JS]什麼是閉包?JS
- 什麼是閉包陷阱?
- 面試官問:Java 執行緒沒有 Running 狀態,為什麼?面試Java執行緒
- 常見的狀態碼都有什麼?網路安全入門學習
- 蘋果生態系統現狀是什麼樣:強大到沒朋友蘋果