MySQL内核源码解读-SQL解析之解析器浅析
MYSQL服務(wù)器接收SQL格式的查詢,首先要對(duì)sql進(jìn)行解析,內(nèi)部將文本格式轉(zhuǎn)換為二進(jìn)制結(jié)構(gòu),這個(gè)轉(zhuǎn)換就是解析器,解析的目的是為了讓優(yōu)化器更好的處理指令,以便以最優(yōu)的路徑,最少的耗時(shí)返回我們想要的結(jié)果。
sql解析器的構(gòu)成:
1、詞法分析(Lexical scanner):作用是將整個(gè)查詢分解為多個(gè)元素。
2、語(yǔ)法規(guī)則(Grammar rule module):尋找sql語(yǔ)法規(guī)則組合,產(chǎn)生一個(gè)序列,執(zhí)行這些規(guī)則相關(guān)的代碼。
1 and 2 產(chǎn)生一棵解析樹(shù),提供給優(yōu)化器使用。
mysql解析器的特殊性在于它直接轉(zhuǎn)換為程序內(nèi)存中的內(nèi)部解析的C/C++結(jié)構(gòu),而一般的解析器是將文本表達(dá)式轉(zhuǎn)換為字節(jié)代碼。
1. 源碼解讀解析器
MySQL語(yǔ)法解析封裝在函數(shù)MYSQLparser中,包含兩個(gè)模塊:詞法分析(Lexical scanner)和語(yǔ)法規(guī)則(Grammar rule module)。詞法分析將整個(gè)SQL語(yǔ)句打碎成一個(gè)個(gè)單詞(Token),而語(yǔ)法規(guī)則模塊則根據(jù)MySQL定義的語(yǔ)法規(guī)則生成對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu),并存儲(chǔ)在對(duì)象THD->LEX結(jié)構(gòu)當(dāng)中。最后優(yōu)化器,根據(jù)這里的數(shù)據(jù),生成執(zhí)行計(jì)劃,再調(diào)用存儲(chǔ)引擎接口執(zhí)行。詞法分析和語(yǔ)法規(guī)則模塊有兩個(gè)較成熟的開(kāi)源工具Flex和Bison分別用來(lái)解決這兩個(gè)問(wèn)題。MySQL出于性能和靈活考慮,選擇了自行完成詞法解析部分,語(yǔ)法規(guī)則部分使用Bison。詞法解析和Bison溝通的核心函數(shù)是由詞法解析器提供的函數(shù)接口yylex(),在Bison中,必要的時(shí)候調(diào)用yylex()獲得詞法解析的數(shù)據(jù),完成自己的語(yǔ)法解析。Bison的入口為yyparse(),在MySQL中定義為MYSQLParse。
1.1. 解析示意
Bison在做語(yǔ)法解析后,會(huì)將解析結(jié)果(解析樹(shù)/AST)存儲(chǔ)在THD::LEX中,通過(guò)存儲(chǔ)WHERE的數(shù)據(jù)結(jié)構(gòu)來(lái)查看語(yǔ)法解析的結(jié)果。
1.2. 解析樹(shù)的ITEM對(duì)象
在MYSQL中,有以下ITEM大類型:
FIELD_ITEM, FUNC_ITEM,
SUM_FUNC_ITEM,
STRING_ITEM,
INT_ITEM,
REAL_ITEM,
NULL_ITEM,
VARBIN_ITEM,
COPY_STR_ITEM,
FIELD_AVG_ITEM,
DEFAULT_VALUE_ITEM,
PROC_ITEM,COND_ITEM,
REF_ITEM,
FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM,
INSERT_VALUE_ITEM,
SUBSELECT_ITEM,
ROW_ITEM,
CACHE_ITEM,
TYPE_HOLDER,
PARAM_ITEM
其中許多ITEM還有小類,如Item_func有如下小類型:
UNKNOWN_FUNC,
EQ_FUNC,
EQUAL_FUNC,
NE_FUNC,
LT_FUNC,
LE_FUNC,
GE_FUNC,
GT_FUNC,FT_FUNC,
LIKE_FUNC,
NOTLIKE_FUNC,
ISNULL_FUNC,
ISNOTNULL_FUNC,
COND_AND_FUNC,
COND_OR_FUNC,
COND_XOR_FUNC,
BETWEEN, IN_FUNC,
INTERVAL_FUNC,
ISNOTNULLTEST_FUNC,
SP_EQUALS_FUNC,
SP_DISJOINT_FUNC,
SP_INTERSECTS_FUNC,
SP_TOUCHES_FUNC,
SP_CROSSES_FUNC,
SP_WITHIN_FUNC,
SP_CONTAINS_FUNC,
SP_OVERLAPS_FUNC,
SP_STARTPOINT,
SP_ENDPOINT,
SP_EXTERIORRING,
SP_POINTN,
SP_GEOMETRYN,
SP_INTERIORRINGN,
NOT_FUNC,
NOT_ALL_FUNC,
NOW_FUNC,
VAR_VALUE_FUNC
1.3. ITEM語(yǔ)法樹(shù)
1.4. FIELD 類型
enum enum_field_types {
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_SHORT,MYSQL_TYPE_LONG,
MYSQL_TYPE_FLOAT,MYSQL_TYPE_DOUBLE,
MYSQL_TYPE_NULL,MYSQL_TYPE_TIMESTAMP,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME,MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
MYSQL_TYPE_MEDIUM_BLOB=250,
MYSQL_TYPE_LONG_BLOB=251,
MYSQL_TYPE_BLOB=252,
MYSQL_TYPE_VAR_STRING=253,
MYSQL_TYPE_STRING=254,
MYSQL_TYPE_GEOMETRY=255
};
1.5. FIELD和ITEM的關(guān)系
通過(guò)Item類中的tmp_table_field_from_field_type函數(shù)將一個(gè)Item類轉(zhuǎn)化為一個(gè)Filed類返回,例如
Item_int ->Field_longlong
Item_real->Field_double
Item_string->Field_string
1.6. Bison語(yǔ)法中的WHERE
| ---->expr or expr |
| ---->expr amd expr |
| ---->…………………… |
| ---->simple_expr comp_op simple_expr |
where 要點(diǎn):
where_clause:
/ empty / {}
| WHERE expr
{
THD->lex->current_select->where = $2
}
expr:
...
| expr and expr
{
$$ = new (YYTHD->mem_root) Item_cond_and($1, $3)
}
|ident comp_op NUM /簡(jiǎn)化版/
{
$$ = new Item_func_ge(a, b); /簡(jiǎn)化版/
}
通過(guò)解析就能生成where的語(yǔ)法樹(shù)。
Where解析樹(shù)的分支:如圖
1.7. 總結(jié)
解析器的最終執(zhí)行結(jié)果就是解析樹(shù),sql語(yǔ)法的復(fù)雜性要求具有同樣復(fù)雜程度的結(jié)構(gòu),通過(guò)這種結(jié)構(gòu)有效存儲(chǔ)用于執(zhí)行每個(gè)可能使用到的sql語(yǔ)句所需的信息。
解析樹(shù)中重要的兩個(gè)對(duì)象【enum_sql_command和select_lex】, sql_command顯示sql類型,execute_command則指導(dǎo)調(diào)用相關(guān)函數(shù)。通過(guò)內(nèi)核級(jí)別的調(diào)用,最終生成解析樹(shù),提供給優(yōu)化器,最終完成我們的操作指令。
?
2. 參考資料
[1]OReilly Understanding MySQL Internals
[2]MySQL內(nèi)核:InnoDB存儲(chǔ)引擎
[3]OReilly
[4]《lex與yacc》(第二版)
[5]《flex與bison》(第二版)
[6]Bison操作手冊(cè): http://www.gnu.org/software/bison/manual/bison.html
本文由京東商城數(shù)據(jù)庫(kù)技術(shù)部郭光欣提供。
總結(jié)
以上是生活随笔為你收集整理的MySQL内核源码解读-SQL解析之解析器浅析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 20181009-9 每周例行报告
- 下一篇: 一张图告诉你BCH路线分歧的现状