成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

拯救DBA!美團(tuán)SQL解析探索實(shí)踐

數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)作為核心的基礎(chǔ)組件,是需要重點(diǎn)保護(hù)的對(duì)象。任何一個(gè)線上的不慎操作,都有可能給數(shù)據(jù)庫(kù)帶來(lái)嚴(yán)重的故障,從而給業(yè)務(wù)造成巨大的損失。

數(shù)據(jù)庫(kù)作為核心的基礎(chǔ)組件,是需要重點(diǎn)保護(hù)的對(duì)象。任何一個(gè)線上的不慎操作,都有可能給數(shù)據(jù)庫(kù)帶來(lái)嚴(yán)重的故障,從而給業(yè)務(wù)造成巨大的損失。

為了避免這種損失,一般會(huì)在管理上下功夫。比如為研發(fā)人員制定數(shù)據(jù)庫(kù)開發(fā)規(guī)范;新上線的 SQL,需要 DBA 進(jìn)行審核;維護(hù)操作需要經(jīng)過(guò)領(lǐng)導(dǎo)審批等等。

而且如果希望能夠有效地管理這些措施,需要有效的數(shù)據(jù)庫(kù)培訓(xùn),還需要 DBA 細(xì)心的進(jìn)行 SQL 審核。

很多中小型創(chuàng)業(yè)公司,可以通過(guò)設(shè)定規(guī)范、進(jìn)行培訓(xùn)、完善審核流程來(lái)管理數(shù)據(jù)庫(kù)。

隨著美團(tuán)業(yè)務(wù)的不斷發(fā)展和壯大,上述措施的實(shí)施成本越來(lái)越高。如何更多的依賴技術(shù)手段,來(lái)提高效率,越來(lái)越受到重視。

業(yè)界已有不少基于 MySQL 源碼開發(fā)的 SQL 審核、優(yōu)化建議等工具,極大的減輕了 DBA 的 SQL 審核負(fù)擔(dān)。

那么我們能否繼續(xù)擴(kuò)展 MySQL 的源碼,來(lái)輔助 DBA 和研發(fā)人員來(lái)進(jìn)一步提高效率呢?

比如,更全面的 SQL 優(yōu)化功能;多維度的慢查詢分析;輔助故障分析等。要實(shí)現(xiàn)上述功能,其中最核心的技術(shù)之一就是 SQL 解析。

現(xiàn)狀與場(chǎng)景

SQL 解析是一項(xiàng)復(fù)雜的技術(shù),一般都是由數(shù)據(jù)庫(kù)廠商來(lái)掌握,當(dāng)然也有公司專門提供 SQL 解析的 API。

由于這幾年 MySQL 數(shù)據(jù)庫(kù)中間件的興起,需要支持讀寫分離、分庫(kù)分表等功能,就必須從 SQL 中抽出表名、庫(kù)名以及相關(guān)字段的值。

因此像 Java 語(yǔ)言編寫的 Druid,C 語(yǔ)言編寫的 MaxScale,Go 語(yǔ)言編寫的 Kingshard 等,都會(huì)對(duì) SQL 進(jìn)行部分解析。

而真正把 SQL 解析技術(shù)用于數(shù)據(jù)庫(kù)維護(hù)的產(chǎn)品較少,主要有如下幾個(gè):

  • 美團(tuán)點(diǎn)評(píng)開源的 SQLAdvisor。它基于 MySQL 原生態(tài)詞法解析,結(jié)合分析 SQL 中的 where 條件、聚合條件、多表 Join 關(guān)系給出索引優(yōu)化建議。
  • 去哪兒開源的 Inception。側(cè)重于根據(jù)內(nèi)置的規(guī)則,對(duì) SQL 進(jìn)行審核。
  • 阿里的 Cloud DBA。根據(jù)官方文檔介紹,其也是提供 SQL 優(yōu)化建議和改寫。

上述產(chǎn)品都有非常合適的應(yīng)用場(chǎng)景,在業(yè)界也被廣泛使用。但是 SQL 解析的應(yīng)用場(chǎng)景遠(yuǎn)遠(yuǎn)沒有被充分發(fā)掘,比如:

  • 基于表粒度的慢查詢報(bào)表。比如,一個(gè) Schema 中包含了屬于不同業(yè)務(wù)線的數(shù)據(jù)表,那么從業(yè)務(wù)線的角度來(lái)說(shuō),其希望提供表粒度的慢查詢報(bào)表。

生成 SQL 特征。將 SQL 語(yǔ)句中的值替換成問(wèn)號(hào),方便 SQL 歸類。雖然可以使用正則表達(dá)式實(shí)現(xiàn)相同的功能,但是其 Bug 較多,可以參考 pt-query-digest。

  • 比如 pt-query-digest 中,會(huì)把遇到的數(shù)字都替換成“?”,導(dǎo)致無(wú)法區(qū)別不同數(shù)字后綴的表。
  • 高危操作確認(rèn)與規(guī)避。比如,DBA 不小心 Drop 數(shù)據(jù)表,而此類操作,目前還無(wú)有效的工具進(jìn)行回滾,尤其是大表,其后果將是災(zāi)難性的。
  • SQL 合法性判斷。為了安全、審計(jì)、控制等方面的原因,美團(tuán)點(diǎn)評(píng)不會(huì)讓研發(fā)人員直接操作數(shù)據(jù)庫(kù),而是提供 RDS 服務(wù)。

尤其是對(duì)于數(shù)據(jù)變更,需要研發(fā)人員的上級(jí)主管進(jìn)行業(yè)務(wù)上的審批。如果研發(fā)人員,寫了一條語(yǔ)法錯(cuò)誤的 SQL,而 RDS 無(wú)法判斷該 SQL 是否合法,就會(huì)造成不必要的溝通成本。

因此為了讓所有有需要的業(yè)務(wù)都能方便的使用 SQL 解析功能,我們認(rèn)為應(yīng)該具有如下特性:

  • 直接暴露 SQL 解析接口,使用盡量簡(jiǎn)單。比如,輸入 SQL,則輸出表名、特征和優(yōu)化建議。
  • 接口的使用不依賴于特定的語(yǔ)言,否則維護(hù)和使用的代價(jià)太高。比如,以 HTTP 等方式提供服務(wù)。

千里之行,始于足下,下面我先介紹下 SQL 的解析原理。

SQL 解析原理

SQL 解析與優(yōu)化屬于編譯器范疇,和 C 等其他語(yǔ)言的解析沒有本質(zhì)的區(qū)別。

其中分為,詞法分析、語(yǔ)法和語(yǔ)義分析、優(yōu)化、執(zhí)行代碼生成。對(duì)應(yīng)到 MySQL 的部分,如下圖:

圖 1:SQL 解析原理

詞法分析

SQL 解析由詞法分析和語(yǔ)法/語(yǔ)義分析兩個(gè)部分組成。詞法分析主要是把輸入轉(zhuǎn)化成一個(gè)個(gè) Token。其中 Token 中包含 Keyword(也稱 Symbol)和非 Keyword。

例如,SQL 語(yǔ)句 select username from userinfo,在分析之后,會(huì)得到 4 個(gè) Token。

其中有 2 個(gè) Keyword,分別為 select 和 from:

通常情況下,詞法分析可以使用 Flex 來(lái)生成,但是 MySQL 并未使用該工具,而是手寫了詞法分析部分(據(jù)說(shuō)是為了效率和靈活性,參考此文)。具體代碼在 sql/lex.h 和 sql/sql_lex.cc 文件中。

MySQL 中的 Keyword 定義在 sql/lex.h 中,如下為部分 Keyword:

  1. "&&",               SYM(AND_AND_SYM)}, 
  2. "<",                SYM(LT)}, 
  3. "<=",               SYM(LE)}, 
  4. "<>",               SYM(NE)}, 
  5. "!=",               SYM(NE)}, 
  6. "=",                SYM(EQ)}, 
  7. ">",                SYM(GT_SYM)}, 
  8. ">=",               SYM(GE)}, 
  9. "<<",               SYM(SHIFT_LEFT)}, 
  10. ">>",               SYM(SHIFT_RIGHT)}, 
  11. "<=>",              SYM(EQUAL_SYM)}, 
  12. "ACCESSIBLE",       SYM(ACCESSIBLE_SYM)}, 
  13. "ACTION",           SYM(ACTION)}, 
  14. "ADD",              SYM(ADD)}, 
  15. "AFTER",            SYM(AFTER_SYM)}, 
  16. "AGAINST",          SYM(AGAINST)}, 
  17. "AGGREGATE",        SYM(AGGREGATE_SYM)}, 
  18. "ALL",              SYM(ALL)}, 

詞法分析的核心代碼在 sql/sql_lex.c 文件中的 MySQLLex→lex_one_Token,有興趣的同學(xué)可以下載源碼研究。

語(yǔ)法分析

語(yǔ)法分析就是生成語(yǔ)法樹的過(guò)程。這是整個(gè)解析過(guò)程中最精華,最復(fù)雜的部分,不過(guò)這部分 MySQL 使用了 Bison 來(lái)完成。

即使如此,如何設(shè)計(jì)合適的數(shù)據(jù)結(jié)構(gòu)以及相關(guān)算法,去存儲(chǔ)和遍歷所有的信息,也是值得在這里研究的。

語(yǔ)法分析樹

SQL 語(yǔ)句:

  1. select username, ismale from userinfo where age > 20 and level > 5 and 1 = 1 

會(huì)生成如下語(yǔ)法樹:

圖 2:語(yǔ)法樹

對(duì)于未接觸過(guò)編譯器實(shí)現(xiàn)的同學(xué),肯定會(huì)好奇如何才能生成這樣的語(yǔ)法樹。其背后的原理都是編譯器的范疇。

本人也是在學(xué)習(xí) MySQL 源碼過(guò)程中,閱讀了部分內(nèi)容。由于編譯器涉及的內(nèi)容過(guò)多,本人經(jīng)歷和時(shí)間有限,不做過(guò)多探究。

從工程的角度來(lái)說(shuō),學(xué)會(huì)如何使用 Bison 去構(gòu)建語(yǔ)法樹,來(lái)解決實(shí)際問(wèn)題,對(duì)我們的工作也許有更大幫助。下面我就以 Bison 為基礎(chǔ),探討該過(guò)程。

MySQL 語(yǔ)法分析樹生成過(guò)程

全部的源碼在 sql/sql_yacc.yy 中,在 MySQL 5.6 中有 17K 行左右代碼。這里列出涉及到的 SQL:

  1. select username, ismale from userinfo where age > 20 and level > 5 and 1 = 1  

解析過(guò)程的部分代碼摘錄出來(lái)。有了 Bison 之后,SQL 解析的難度也沒有想象的那么大,特別是這里給出了解析的脈絡(luò)之后。

  1. select /*select語(yǔ)句入口*/: 
  2.  
  3.           select_init 
  4.  
  5.           { 
  6.  
  7.             LEX *lex= Lex; 
  8.  
  9.             lex->sql_command= SQLCOM_SELECT; 
  10.  
  11.           } 
  12.  
  13.         ; 
  14.  
  15. select_init: 
  16.           SELECT_SYM /*select 關(guān)鍵字*/ select_init2 
  17.  
  18.         | '(' select_paren ')' union_opt 
  19.  
  20.         ; 
  21.  
  22. select_init2: 
  23.           select_part2 
  24.           { 
  25.             LEX *lex= Lex; 
  26.             SELECT_LEX * sel= lex->current_select; 
  27.             if (lex->current_select->set_braces(0)) 
  28.             { 
  29.               my_parse_error(ER(ER_SYNTAX_ERROR)); 
  30.               MYSQL_YYABORT; 
  31.             } 
  32.             if (sel->linkage == UNION_TYPE && 
  33.                 sel->master_unit()->first_select()->braces) 
  34.             { 
  35.               my_parse_error(ER(ER_SYNTAX_ERROR)); 
  36.               MYSQL_YYABORT; 
  37.             } 
  38.           } 
  39.           union_clause 
  40.         ; 
  41. select_part2: 
  42.           { 
  43.             LEX *lex= Lex; 
  44.             SELECT_LEX *sel= lex->current_select; 
  45.             if (sel->linkage != UNION_TYPE) 
  46.               mysql_init_select(lex); 
  47.             lex->current_select->parsing_place= SELECT_LIST; 
  48.           } 
  49.  
  50.           select_options select_item_list /*解析列名*/ 
  51.           { 
  52.             Select->parsing_place= NO_MATTER; 
  53.           } 
  54.           select_into select_lock_type 
  55.         ; 
  56.  
  57. select_into: 
  58.           opt_order_clause opt_limit_clause {} 
  59.         | into 
  60.         | select_from /*from 字句*/ 
  61.         | into select_from 
  62.         | select_from into 
  63.         ; 
  64. select_from: 
  65.           FROM join_table_list /*解析表名*/ where_clause /*where字句*/ group_clause having_clause 
  66.           opt_order_clause opt_limit_clause procedure_analyse_clause 
  67.           { 
  68.             Select->context.table_list= 
  69.               Select->context.first_name_resolution_table= 
  70.                 Select->table_list.first
  71.           } 
  72.         | FROM DUAL_SYM where_clause opt_limit_clause 
  73.           /* oracle compatibility: oracle always requires FROM clause, 
  74.              and DUAL is system table without fields. 
  75.              Is "SELECT 1 FROM DUAL" any better than "SELECT 1" ? 
  76.           Hmmm :) */ 
  77.         ; 
  78.  
  79. where_clause: 
  80.           /* empty */  { Select->where= 0; } 
  81.         | WHERE 
  82.           { 
  83.             Select->parsing_place= IN_WHERE; 
  84.           } 
  85.           expr /*各種表達(dá)式*/ 
  86.           { 
  87.             SELECT_LEX *selectSelect
  88.             select->where= $3; 
  89.             select->parsing_place= NO_MATTER; 
  90.             if ($3) 
  91.               $3->top_level_item(); 
  92.           } 
  93.         ; 
  94.  
  95. /* all possible expressions */ 
  96. expr: 
  97.            | expr and expr %prec AND_SYM 
  98.           { 
  99.             /* See comments in rule expr: expr or expr */ 
  100.             Item_cond_and *item1; 
  101.             Item_cond_and *item3; 
  102.             if (is_cond_and($1)) 
  103.             { 
  104.               item1= (Item_cond_and*) $1; 
  105.               if (is_cond_and($3)) 
  106.               { 
  107.                 item3= (Item_cond_and*) $3; 
  108.                 /* 
  109.                   (X1 AND X2) AND (Y1 AND Y2) ==> AND (X1, X2, Y1, Y2) 
  110.                 */ 
  111.                 item3->add_at_head(item1->argument_list()); 
  112.                 $$ = $3; 
  113.               } 
  114.               else 
  115.               { 
  116.                 /* 
  117.                   (X1 AND X2) AND Y ==> AND (X1, X2, Y) 
  118.                 */ 
  119.                 item1->add($3); 
  120.                 $$ = $1; 
  121.               } 
  122.             } 
  123.             else if (is_cond_and($3)) 
  124.             { 
  125.               item3= (Item_cond_and*) $3; 
  126.               /* 
  127.                 X AND (Y1 AND Y2) ==> AND (X, Y1, Y2) 
  128.               */ 
  129.               item3->add_at_head($1); 
  130.               $$ = $3; 
  131.             } 
  132.             else 
  133.             { 
  134.               /* X AND Y */ 
  135.               $$ = new (YYTHD->mem_root) Item_cond_and($1, $3); 
  136.               if ($$ == NULL
  137.                 MYSQL_YYABORT; 
  138.             } 
  139.           } 

在大家瀏覽上述代碼的過(guò)程,會(huì)發(fā)現(xiàn) Bison 中嵌入了 C++ 的代碼。通過(guò) C++ 代碼,把解析到的信息存儲(chǔ)到相關(guān)對(duì)象中。

例如表信息會(huì)存儲(chǔ)到 TABLE_LIST 中,order_list 存儲(chǔ) order by 子句里的信息,where 字句存儲(chǔ)在 Item 中。

有了這些信息,再輔助以相應(yīng)的算法就可以對(duì) SQL 進(jìn)行更進(jìn)一步的處理了。

核心數(shù)據(jù)結(jié)構(gòu)及其關(guān)系

在 SQL 解析中,最核心的結(jié)構(gòu)是 SELECT_LEX,其定義在 sql/sql_lex.h 中。下面僅列出與上述例子相關(guān)的部分。

圖 3:SQL 解析樹結(jié)構(gòu)

上面圖示中,列名 username、ismale 存儲(chǔ)在 item_list 中,表名存儲(chǔ)在 table_list 中,條件存儲(chǔ)在 where 中。

其中以 where 條件中的 Item 層次結(jié)構(gòu)最深,表達(dá)也較為復(fù)雜,如下圖所示:

圖 4:where 條件

SQL 解析應(yīng)用

為了更深入的了解 SQL 解析器,這里給出 2 個(gè)應(yīng)用 SQL 解析的例子。

無(wú)用條件去除

無(wú)用條件去除屬于優(yōu)化器的邏輯優(yōu)化范疇,可以僅僅根據(jù) SQL 本身以及表結(jié)構(gòu)即可完成,其優(yōu)化的情況也是較多的,代碼在 sql/sql_optimizer.cc 文件中的 remove_eq_conds 函數(shù)。

為了避免過(guò)于繁瑣的描述,以及大段代碼的粘貼,這里通過(guò)圖來(lái)分析以下四種情況:

  • 1=1 and (m > 3 and n > 4)
  • 1=2 and (m > 3 and n > 4)
  • 1=1 or (m > 3 and n > 4)
  • 1=2 or (m > 3 and n > 4)

圖 5:無(wú)用條件去除 a

圖 6:無(wú)用條件去除 b

圖 7:無(wú)用條件去除 c

圖 8:無(wú)用條件去除 d

如果對(duì)其代碼實(shí)現(xiàn)有興趣的同學(xué),需要對(duì) MySQL 中的一個(gè)重要數(shù)據(jù)結(jié)構(gòu) Item 類有所了解。

因?yàn)槠浔容^復(fù)雜,所以 MySQL 官方文檔,專門介紹了 Item 類。阿里的 MySQL 小組,也有類似的文章。如需更詳細(xì)的了解,就需要去查看源碼中 sql/item_* 等文件。

SQL 特征生成

為了確保數(shù)據(jù)庫(kù),這一系統(tǒng)基礎(chǔ)組件穩(wěn)定、高效運(yùn)行,業(yè)界有很多輔助系統(tǒng)。比如慢查詢系統(tǒng)、中間件系統(tǒng)。

這些系統(tǒng)采集、收到 SQL 之后,需要對(duì) SQL 進(jìn)行歸類,以便統(tǒng)計(jì)信息或者應(yīng)用相關(guān)策略。歸類時(shí),通常需要獲取 SQL 特征。比如 SQL:

  1. select username, ismale from userinfo where age > 20 and level > 5; 

SQL 特征為:

  1. select username, ismale from userinfo where age > ? and level > ?  

業(yè)界著名的慢查詢分析工具 pt-query-digest,通過(guò)正則表達(dá)式實(shí)現(xiàn)這個(gè)功能但是這類處理辦法 Bug 較多。接下來(lái)就介紹如何使用 SQL 解析,完成 SQL 特征的生成。

SQL特征生成分兩部分組成:

  • 生成 Token 數(shù)組
  • 根據(jù) Token 數(shù)組,生成 SQL 特征

首先回顧在詞法解析章節(jié),我們介紹了 SQL 中的關(guān)鍵字,并且每個(gè)關(guān)鍵字都有一個(gè) 16 位的整數(shù)對(duì)應(yīng),而非關(guān)鍵字統(tǒng)一用 ident 表示,其也對(duì)應(yīng)了一個(gè) 16 位整數(shù)。如下表:

將一個(gè) SQL 轉(zhuǎn)換成特征的過(guò)程:

在 SQL 解析過(guò)程中,可以很方便的完成 Token 數(shù)組的生成。而一旦完成 Token 數(shù)組的生成,就可以很簡(jiǎn)單的完成 SQL 特征的生成。

SQL 特征被廣泛用于各個(gè)系統(tǒng)中,比如 pt-query-digest 需要根據(jù)特征對(duì) SQL 歸類,然而其基于正則表達(dá)式的實(shí)現(xiàn)有諸多 Bug。

下面列舉幾個(gè)已知 Bug:

學(xué)習(xí)建議

最近,在對(duì) SQL 解析器和優(yōu)化器探索的過(guò)程中,從一開始的茫然無(wú)措到有章可循,也總結(jié)了一些心得體會(huì),在這里跟大家分享一下:

  • 閱讀相關(guān)書籍,書籍能給我們一個(gè)系統(tǒng)的認(rèn)識(shí)解析器和優(yōu)化器的角度。但是該類針對(duì) MySQL 的書籍市面上很少,目前中文作品可以看下《數(shù)據(jù)庫(kù)查詢優(yōu)化器的藝術(shù):原理解析與SQL性能優(yōu)化》。
  • 閱讀源碼,但是***以某個(gè)版本為基礎(chǔ),比如 MySQL 5.6.23,因?yàn)?SQL 解析、優(yōu)化部分的代碼在不斷變化。尤其是在跨越大的版本時(shí),改動(dòng)力度大。
  • 多使用 GDB 調(diào)試,驗(yàn)證自己的猜測(cè),檢驗(yàn)閱讀質(zhì)量。
  • 需要寫相關(guān)代碼驗(yàn)證,只有寫出來(lái)了才能算真正的掌握。

作者:廣友、金龍、邢帆

簡(jiǎn)介:廣友,美團(tuán)到店綜合事業(yè)群資深 MySQL DBA,2012 年畢業(yè)于中國(guó)科學(xué)技術(shù)大學(xué),2017 年加入美團(tuán)點(diǎn)評(píng),長(zhǎng)期致力于 MySQL 及周邊工具的研究。

金龍,2014 年加入美團(tuán),主要從事相關(guān)的數(shù)據(jù)庫(kù)運(yùn)維、高可用和相關(guān)的運(yùn)維平臺(tái)建設(shè)。

邢帆,美團(tuán) DBA,2017 年研究生畢業(yè)后加入美團(tuán)點(diǎn)評(píng),目前對(duì) MySQL 運(yùn)維有一定經(jīng)驗(yàn),并編寫了一些自動(dòng)化腳本。

責(zé)任編輯:武曉燕 來(lái)源: 美團(tuán)技術(shù)團(tuán)隊(duì)(meituantech)
相關(guān)推薦

2022-08-12 12:23:28

神經(jīng)網(wǎng)絡(luò)優(yōu)化

2022-04-29 09:10:00

算法人工智能技術(shù)

2022-05-20 11:01:06

模型性能框架

2018-12-14 11:04:56

數(shù)據(jù)庫(kù)運(yùn)維智能

2022-03-17 12:00:48

異構(gòu)業(yè)務(wù)實(shí)踐

2019-01-14 08:18:43

DBA數(shù)據(jù)庫(kù)運(yùn)維

2019-08-23 13:10:39

美團(tuán)點(diǎn)評(píng)Kubernetes集群管理

2022-04-15 10:30:03

美團(tuán)技術(shù)實(shí)踐

2018-07-17 14:25:02

SQL解析美團(tuán)點(diǎn)評(píng)MySQL

2022-08-09 09:18:47

優(yōu)化實(shí)踐

2017-06-01 10:52:35

互聯(lián)網(wǎng)

2018-10-29 15:50:23

深度學(xué)習(xí)工程實(shí)踐技術(shù)

2022-02-14 16:08:15

開源項(xiàng)目線程池動(dòng)態(tài)可監(jiān)控

2018-03-28 09:53:50

Android架構(gòu)演進(jìn)

2022-03-15 10:20:00

云原生系統(tǒng)實(shí)踐

2022-03-17 21:42:20

美團(tuán)插件技術(shù)

2023-11-14 12:07:43

美團(tuán)沙龍

2022-06-17 11:54:17

數(shù)據(jù)模型系統(tǒng)

2018-07-13 09:53:27

移動(dòng)應(yīng)用美團(tuán)代碼

2018-10-19 14:16:09

Flink數(shù)據(jù)倉(cāng)庫(kù)數(shù)據(jù)系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久国| 亚洲瑟瑟 | 精品国产欧美 | 午夜小电影 | 日韩午夜影院 | 欧美在线视频一区 | 国产日韩久久久久69影院 | 久久99久久99 | 干干干操操操 | 欧美日韩国产一区二区三区 | 波多野结衣一区二区三区在线观看 | 天天摸天天看 | 欧美黄在线观看 | 欧美日韩精品一区二区三区四区 | 免费看的av | 国产成都精品91一区二区三 | 欧美色图综合网 | 久久久人成影片一区二区三区 | 精品免费国产 | 亚洲精品亚洲人成人网 | 日韩高清一区二区 | 羞羞的视频免费观看 | 精品日韩在线观看 | 免费视频中文字幕 | 久久精品16 | 啪一啪在线视频 | 国产视频一区二区 | 国产99久久精品一区二区永久免费 | 国产精品久久久久久久白浊 | 国产精品久久久久一区二区三区 | 亚洲婷婷一区 | av在线一区二区三区 | 99精品视频在线 | 99在线资源| 97人人干| 九九综合 | 久精品久久| 久久ww| 欧美激情免费在线 | 成人欧美一区二区三区黑人孕妇 | 精品在线一区二区三区 |