mysql學習之mysql如何執行查詢語句(1)

mysql專欄爲你彌補這塊的短板

後續我會在這塊給大家帶來mysql方面的知識,分享我在這塊的經驗。
mysql學習是一個漫長的過程,我希望大家能夠不要浮躁,靜下心來好好的學習基礎知識,先把心法學會了,招式就是千變萬化。平時我們使用數據庫,看到的通常是一個整體。比如,你有一個最簡單的表,表裏有一個字段X、下面有一個執行語句:

mysql>select * from mytable where X=?;
或者更加複雜的語句。。。我這裏就不在舉例了。

我們看到給出一個語句,如果數據庫有數據就會返回相應的結果。卻不知道這條語句在MYSQL內部是如何執行的,我今天就給大家拆解一下MYSQL,希望這個拆解過程能讓你對MYSQL有更深入的理解,這樣我們遇到一些問題,或者異常我們能夠快速的定位並且解決問題。
先看一下MYSQL官方的架構:
在這裏插入圖片描述

連接器
第一步,你會先連接到數據庫,這個時候就是mysql連接器負責跟客戶端建立連接,獲取權限,管理連接。
linux命令連接mysql如下:

mysql -h&ip -P&port -u&username -p&password
不建議直接輸入密碼,存在安全隱患,最好直接-p enter 輸入你的密碼

在完成和服務器端TCP的三次握手後,就會驗證身份,如果用戶名和密碼不對就會提示ERROR 1045 (28000): Access denied for user ‘meiling’@‘yourip’ (using password: YES)

如果登錄成功後,我們在通過root權限對其修改權限,是不影響已經登錄後權限的限制。我就不列出來了,大家可以自己嘗試一下。

連接完成後,我們不操作任何命令,連接就處於空閒狀態,我們用show processlist看看情況。
在這裏插入圖片描述
可以看到狀態是 "sleep"就是空閒狀態客戶端很久都沒操作,連接器就會自動斷開。這個時間的參數可以看 wait_timeout,默認是8小時。

mysql> show variables like '%wait_timeout%';
+--------------------------+----------+
| Variable_name            | Value    |
+--------------------------+----------+
| innodb_lock_wait_timeout | 50       |
| lock_wait_timeout        | 31536000 |
| wait_timeout             | 28800    |
+--------------------------+----------+
3 rows in set
mysql> 

我們可以看到是28800秒,換算成小時就是8個小時。你們可以自己看一下這個參數。

數據庫經典8小時問題,就是這個默認參數如果發現一個連接的空閒時間超過8小時,將會在數據庫端自動關閉這個連接。而數據源並不知道這個連接已經關閉了,當它將這個無用的連接返回給某個dao時,dao就會報無法獲取connection異常。
所以我們可以針對這個參數來防止線上問題的發生哦,這個比較隱患。
1.我們可以適當的調整timeout的大小。
2.通過應用層當有空閒的連接的時候,就去激活一下,免得過期造成連接丟失。

數據的連接我們儘量的減少連接次數,連接的過程非常的複雜,太耗費資源,基本上都是長連接。

案例:有一次我們線上的數據庫宕機了,發現非常多的連接導致內存漲的非常的快,長期累積的長連接導致我們內存佔用過大,被系統強制殺掉了mysql進程。
原因分析:就是因爲mysql在執行過程中使用的內存是在連接對象管理的,這些資源只會在連接斷開後纔會釋放。
1,我們就在應用程序裏面定期斷開長連接,具體的實現我會專門有一篇文章(如何斷開連接)
2,通過mysql_reset_connection方式來重置連接。下面是mysql官方提供的api說明

27.8.7.60 mysql_reset_connection()
int mysql_reset_connection(MYSQL *mysql)

說明
重置連接以清除會話狀態。

mysql_reset_connection() 具有類似於 mysql_change_user() 的效果或自動重新連接,但連接未關閉並重新打開,並且未執行重新認證。見 Section 27.8.7.3, “mysql_change_user()” )並參見 Section 27.8.20, “C API Automatic Reconnection Control” )。

與連接相關的狀態受影響如下:

回滾任何活動事務並重置自動提交模式。

釋放所有表鎖。

所有 TEMPORARY 表都已關閉(並已刪除)。

會話系統變量重新初始化爲相應的全局系統變量的值,包括由 SET NAMES 等語句隱式設置的系統變量。

用戶變量設置丟失。

準備好的聲明已經發布。

HANDLER 變量已關閉。

LAST_INSERT_ID() 的值重置爲0。

使用 GET_LOCK() 獲取的鎖定被釋放。

返回值
成功歸零。如果發生錯誤,則爲非零。

查詢緩存

這個很簡單,就是一個key-value的方式。
假如一條sql語句 select * from T where id=1;就會通過key是sql語句去map中查詢是否有這條語句,如果有就直接返回,沒有就執行後面的流程,把數據通過key-value的方式存儲。
查看mysql是否開啓緩存,執行如下命令:

mysql> show variables like '%query_cache_type%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| query_cache_type | ON   |
+------------------+-------+
1 row in set (0.00 sec)

這個可以看到mysql是否開啓了緩存。
但是實際使用的我個人覺得沒什麼必要打開緩存,緩存命中非常的低,我們的業務經常在更改變化,如何一旦有表數據發生變化,緩存就會清除。所以實戰中我們是不會打開緩存的。

命令解析層
如果緩存沒有命中的話,就會分析當前的sql,分析當前的語句是查詢,還是ddl,還是其他的命令。

mysql>select * from mytable where X=?; //繼續解說這條

我們輸入的select 這個關鍵詞就會識別出來是查詢模塊,在分別把mytable識別成表名 mytable ,把字符串識X別成列X。

後面就會做語法的分析,如果語法不對就會提示你錯誤。

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘ad’ at line 1

我們只需要關注的是 "user near"的內容,基本上就可以知道是什麼錯誤了。

優化器
經過分析器後,mysql就知道你要做什麼了,在調用執行器錢,還要做一些優化的處理。
優化器就是選擇哪種方案去執行我們的sql。
簡單的使用 OPTIMIZER_TRACE
查看是否開啓優化器

mysql> show variables like '%optimizer_trace%';
+------------------------------+----------------------------------------------------------------------------+
| Variable_name                | Value                                                                      |
+------------------------------+----------------------------------------------------------------------------+
| optimizer_trace              | enabled=off,one_line=off                                                   |
| optimizer_trace_features     | greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on |
| optimizer_trace_limit        | 1                                                                          |
| optimizer_trace_max_mem_size | 16384                                                                      |
| optimizer_trace_offset       | -1                                                                         |
+------------------------------+----------------------------------------------------------------------------+

開啓優化器

mysql> set session optimizer_trace='enabled=on';
Query OK, 0 rows affected
mysql> show variables like '%optimizer_trace%';
+------------------------------+----------------------------------------------------------------------------+
| Variable_name                | Value                                                                      |
+------------------------------+----------------------------------------------------------------------------+
| optimizer_trace              | enabled=on,one_line=off                                                    |
| optimizer_trace_features     | greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on |
| optimizer_trace_limit        | 1                                                                          |
| optimizer_trace_max_mem_size | 16384                                                                      |
| optimizer_trace_offset       | -1                                                                         |
+------------------------------+----------------------------------------------------------------------------+
5 rows in set
//執行一條查詢語句
mysql> select * from oc_user where cid='e7cf68e15ba3480f';
+-----+------------------+----------+-----------+----------+-------------+---------+-------+-----------+------------+------------+--------+---------------------+------------+
| id  | cid              | nickname | username  | password | phone       | iconURL | email | ipaddress | devicetype | macaddress | frozen | createtime          | updatetime |
+-----+------------------+----------+-----------+----------+-------------+---------+-------+-----------+------------+------------+--------+---------------------+------------+
| 129 | e7cf68e15ba3480f | NULL     | ac_3Fhtni | NULL     | 13966789831 | NULL    | NULL  | NULL      | NULL       | NULL       | NULL   | 2017-11-27 14:18:56 | NULL       |
+-----+------------------+----------+-----------+----------+-------------+---------+-------+-----------+------------+------------+--------+---------------------+------------+
1 row in set

查看優化器如何執行的

mysql> select trace from information_schema.optimizer_trace;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| trace                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| {
  "steps": [
    {
      "join_preparation": {  //優化準備階段
        "select#": 1,
        "steps": [
          {
          //表示出來查詢的sql語句
            "expanded_query": "/* select#1 */ select `oc_user`.`id` AS `id`,`oc_user`.`cid` AS `cid`,`oc_user`.`nickname` AS `nickname`,`oc_user`.`username` AS `username`,`oc_user`.`password` AS `password`,`oc_user`.`phone` AS `phone`,`oc_user`.`iconURL` AS `iconURL`,`oc_user`.`email` AS `email`,`oc_user`.`ipaddress` AS `ipaddress`,`oc_user`.`devicetype` AS `devicetype`,`oc_user`.`macaddress` AS `macaddress`,`oc_user`.`frozen` AS `frozen`,`oc_user`.`createtime` AS `createtime`,`oc_user`.`updatetime` AS `updatetime` from `oc_user` where (`oc_user`.`cid` = 'e7cf68e15ba3480f')"
          }
        ]
      }
    },
    {
      "join_optimization": {//優化工作的主要階段,包括邏輯和物理的2個階段優化
        "select#": 1,
        "steps": [
          {
            "condition_processing": {//邏輯優化部分
              "condition": "WHERE", //先看where條件,
              "original_condition": "(`oc_user`.`cid` = 'e7cf68e15ba3480f')",
              "steps": [
                {
                  "transformation": "equality_propagation",//邏輯優化,條件優化,等式處理
                  "resulting_condition": "(`oc_user`.`cid` = 'e7cf68e15ba3480f')"
                },
                {
                  "transformation": "constant_propagation",//邏輯優化,條件優化,常量處理
                  "resulting_condition": "(`oc_user`.`cid` = 'e7cf68e15ba3480f')"
                },
                {
                  "transformation": "trivial_condition_removal",,//邏輯優化,條件簡化,條件去除
                  "resulting_condition": "(`oc_user`.`cid` = 'e7cf68e15ba3480f')"
                }
              ]
            }
          },
          {
          //這裏是邏輯優化後 where條件優化結束
            "substitute_generated_columns": {
            }
          },
          {
            "table_dependencies": [//邏輯優化,找出表之間的相互依賴關係,非直接可用的優化方式
              {
                "table": "`oc_user`",//有哪些表
                "row_may_be_null": false,//是否可以不存在行數據
                "map_bit": 0,//從0開始
                "depends_on_map_bits": [
                ]
              }
            ]
          },
          {
            "ref_optimizer_key_uses": [//邏輯優化,找出備選的索引
              {
                "table": "`oc_user`",
                "field": "cid", //這個是索引字段,下面的一樣
                "equals": "'e7cf68e15ba3480f'",
                "null_rejecting": false
              }
            ]
          },
          {
            "rows_estimation": [//邏輯優化, 估算每個表的元組個數. 單表上進行全表掃描和索引掃描的代價估算. 每個索引都估算索引掃描代價(估算行數)
              {
                "table": "`oc_user`", //表名
                "rows": 1,//有多少行
                "cost": 1,//代價,這個值越大,花費的代價越大
                "table_type": "const", //表的類型
                "empty": false//是否爲空
              }
            ]
          },
          {
            "condition_on_constant_tables": "('e7cf68e15ba3480f' = 'e7cf68e15ba3480f')",
            "condition_value": true
          },
          {
            "attaching_conditions_to_tables": {//邏輯優化,儘量吧條件綁定到對應的表上。
              "original_condition": "('e7cf68e15ba3480f' = 'e7cf68e15ba3480f')",
              "attached_conditions_computation": [
              ],
              "attached_conditions_summary": [
              ]
            }
          },
          {
            "refine_plan": [
            ]
          }
        ]
      }
    },
    {
      "join_execution": {
        "select#": 1,
        "steps": [
        ]
      }
    }
  ]
} |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set

執行器
mysql通過分析器知道了要做什麼,優化器該怎麼做,接下來就進入了執行器階段,開始執行語句。
在執行語句的時候,mysql還是要堅持一下執行是否有權限,如果沒有就會返回權限錯誤。
比如我們例子中的mytable表,字段X沒有索引,那麼執行器就是循環的調用InnoDb引擎接口獲取表的數據,然後在對比一下是否和我們傳入的值一樣,如果不是就繼續,是就直接存在結果集。直到取到表的最後一行數據,在把結果集返回給客戶端。
到此,語句執行完畢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章