• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    面向OceanBase的存儲(chǔ)過(guò)程實(shí)現(xiàn)技術(shù)研究

    2014-09-06 10:53:08周敏奇
    關(guān)鍵詞:數(shù)據(jù)庫(kù)語(yǔ)言系統(tǒng)

    朱 濤, 周敏奇, 張 召

    (華東師范大學(xué) 軟件學(xué)院, 上海 200062)

    ?

    面向OceanBase的存儲(chǔ)過(guò)程實(shí)現(xiàn)技術(shù)研究

    朱 濤, 周敏奇, 張 召

    (華東師范大學(xué) 軟件學(xué)院, 上海 200062)

    存儲(chǔ)過(guò)程是一段被命名后保存在數(shù)據(jù)庫(kù)服務(wù)器端,并預(yù)先編譯好的代碼,可以減少前臺(tái)應(yīng)用程序和后臺(tái)數(shù)據(jù)庫(kù)間的網(wǎng)絡(luò)傳輸量. 本文主要研究基于靜態(tài)語(yǔ)言和動(dòng)態(tài)語(yǔ)言,兩種典型的存儲(chǔ)過(guò)程實(shí)現(xiàn)方法,來(lái)闡述存儲(chǔ)過(guò)程實(shí)現(xiàn)的基本原理. 并基于此,進(jìn)一步探討了在OceanBase主存數(shù)據(jù)庫(kù)服務(wù)器中添加存儲(chǔ)過(guò)程模塊的解決方案和技術(shù)難點(diǎn).

    存儲(chǔ)過(guò)程; 數(shù)據(jù)庫(kù)系統(tǒng); SQL

    1 背景簡(jiǎn)介

    在各類(lèi)以數(shù)據(jù)管理為核心的應(yīng)用中,數(shù)據(jù)庫(kù)通常扮演著底層存儲(chǔ)的角色.應(yīng)用服務(wù)器通過(guò)網(wǎng)絡(luò)通信與數(shù)據(jù)庫(kù)服務(wù)器進(jìn)行交互,當(dāng)某些任務(wù)需要多次訪問(wèn)數(shù)據(jù)庫(kù),應(yīng)用服務(wù)器需要與數(shù)據(jù)庫(kù)服務(wù)器進(jìn)行多次的網(wǎng)絡(luò)通信,并傳送大量的中間結(jié)果. 這會(huì)影響應(yīng)用對(duì)用戶查詢的響應(yīng)速度. 為了解決這一問(wèn)題,當(dāng)前主流數(shù)據(jù)庫(kù) ,如Oracle, Mysql, DB2等,均允許用戶在數(shù)據(jù)庫(kù)服務(wù)器端編寫(xiě)程序來(lái)實(shí)現(xiàn)本在應(yīng)用程序段完成的業(yè)務(wù)邏輯. 這段被命名后預(yù)先編譯存儲(chǔ)在數(shù)據(jù)庫(kù)服務(wù)器端的代碼即為存儲(chǔ)過(guò)程[1].

    1.1 存儲(chǔ)過(guò)程簡(jiǎn)介

    存儲(chǔ)過(guò)程是大型數(shù)據(jù)庫(kù)系統(tǒng)中,一組完成特定功能的程序集,經(jīng)編譯后存儲(chǔ)在數(shù)據(jù)庫(kù)中,上層應(yīng)用調(diào)用存儲(chǔ)過(guò)程只需要給出存儲(chǔ)過(guò)程名和相應(yīng)的參數(shù)即可. 這樣可以減少應(yīng)用程序與數(shù)據(jù)庫(kù)間的數(shù)據(jù)交互次數(shù)和數(shù)據(jù)傳輸量. 因此,在一個(gè)以數(shù)據(jù)庫(kù)為核心的應(yīng)用系統(tǒng)中,需要跟數(shù)據(jù)庫(kù)頻繁交互的業(yè)務(wù)邏輯往往用存儲(chǔ)過(guò)程來(lái)完成.

    總的來(lái)說(shuō),存儲(chǔ)過(guò)程具有以下三個(gè)優(yōu)點(diǎn):

    (1) 預(yù)先編譯,運(yùn)行速度快. 如果跟數(shù)據(jù)庫(kù)的交互工作是在前臺(tái)的程序設(shè)計(jì)語(yǔ)言中完成,那么,每次跟數(shù)據(jù)庫(kù)連接,程序中相應(yīng)的SQL語(yǔ)句就要編譯一次,而存儲(chǔ)過(guò)程卻可以一次編譯多次運(yùn)行.

    (2) 前臺(tái)應(yīng)用程序和數(shù)據(jù)庫(kù)服務(wù)器之間只傳存儲(chǔ)過(guò)程名稱(chēng)和參數(shù),網(wǎng)絡(luò)通信量少. 使用存儲(chǔ)過(guò)程能在數(shù)據(jù)庫(kù)服務(wù)器上完成全部對(duì)數(shù)據(jù)庫(kù)的操作,只需返回最終結(jié)果. 從而減少了數(shù)據(jù)庫(kù)服務(wù)器與應(yīng)用程序之間的交互次數(shù)和數(shù)據(jù)傳輸總量.

    (3) 對(duì)數(shù)據(jù)庫(kù)訪問(wèn)封裝,安全性高. 參數(shù)化的存儲(chǔ)過(guò)程可以防止SQL語(yǔ)句的注入式攻擊,并且可以將使用Grant、Deny以及Revoke等語(yǔ)句來(lái)完成=存儲(chǔ)過(guò)程級(jí)別的權(quán)限管理.

    然而,存儲(chǔ)過(guò)程除了以上的三個(gè)優(yōu)點(diǎn)以外,也存在以下的三個(gè)缺點(diǎn):

    (1) 程序調(diào)試?yán)щy. 由于存儲(chǔ)過(guò)程是運(yùn)行在數(shù)據(jù)庫(kù)端的一段代碼,并基于數(shù)據(jù)庫(kù)提供的獨(dú)特的編程語(yǔ)言來(lái)實(shí)現(xiàn). 導(dǎo)致常用的調(diào)試工具不能直接用來(lái)調(diào)試這類(lèi)代碼. 因此,在開(kāi)發(fā)存儲(chǔ)過(guò)程時(shí),通常面臨調(diào)試?yán)щy的問(wèn)題.

    (2) 代碼移植困難. 不像SQL語(yǔ)言,存儲(chǔ)過(guò)程語(yǔ)言并沒(méi)有被標(biāo)準(zhǔn)化. 不同的數(shù)據(jù)庫(kù)支持存儲(chǔ)過(guò)程的開(kāi)發(fā)語(yǔ)言都不盡相同. 當(dāng)Web應(yīng)用使用的數(shù)據(jù)庫(kù)系統(tǒng)發(fā)生變化時(shí),在兩個(gè)數(shù)據(jù)庫(kù)系統(tǒng)上移植相應(yīng)的存儲(chǔ)過(guò)程需要重新開(kāi)發(fā)和調(diào)試.

    (3) 數(shù)據(jù)庫(kù)負(fù)擔(dān)重. 存儲(chǔ)過(guò)程雖然減少了應(yīng)用和數(shù)據(jù)庫(kù)之間的交互,但同時(shí)增加了數(shù)據(jù)庫(kù)的計(jì)算負(fù)擔(dān). 例如,原本對(duì)查詢結(jié)果集的遍歷訪問(wèn)是在應(yīng)用層完成的,數(shù)據(jù)庫(kù)只需要提供相應(yīng)的查詢結(jié)果即可. 但在存儲(chǔ)過(guò)程中,數(shù)據(jù)庫(kù)服務(wù)器不僅要提供查詢結(jié)果,還需要完成遍歷訪問(wèn)以及一些必要的數(shù)據(jù)加工和計(jì)算,并產(chǎn)生最終的結(jié)果返回給上層應(yīng)用.

    1.2 已有數(shù)據(jù)庫(kù)系統(tǒng)對(duì)存儲(chǔ)過(guò)程的支持

    雖然主流的數(shù)據(jù)庫(kù)管理系統(tǒng)都支持存儲(chǔ)過(guò)程,但是它們支持的語(yǔ)法和使用的方法卻有很大區(qū)別. 這是因?yàn)榇鎯?chǔ)過(guò)程還沒(méi)有形成統(tǒng)一的規(guī)范,并且存儲(chǔ)過(guò)程在各個(gè)系統(tǒng)中的實(shí)現(xiàn)也受限于系統(tǒng)本身的設(shè)計(jì). 表1列舉了當(dāng)前一些數(shù)據(jù)庫(kù)支持的存儲(chǔ)過(guò)程語(yǔ)言,其中的數(shù)據(jù)來(lái)源于各自的網(wǎng)站. 從中不難看出,不同數(shù)據(jù)庫(kù)所采用的存儲(chǔ)過(guò)程語(yǔ)言大不一樣. 即便是被多個(gè)數(shù)據(jù)庫(kù)同時(shí)采用的Java語(yǔ)言,其實(shí)際的存儲(chǔ)過(guò)程編程接口還是會(huì)有很大區(qū)別.

    表1 主流數(shù)據(jù)庫(kù)系統(tǒng)存儲(chǔ)過(guò)程開(kāi)發(fā)語(yǔ)言

    事實(shí)上,根據(jù)所使用的開(kāi)發(fā)語(yǔ)言的性質(zhì),存儲(chǔ)過(guò)程的實(shí)現(xiàn)可以分為兩類(lèi):(1)采用靜態(tài)過(guò)程語(yǔ)言實(shí)現(xiàn),例如SQL PL,PSQL,SPL,SQL/PSM,PL/SQL[2]等;(2)采用已有的支持反射機(jī)制的動(dòng)態(tài)編程語(yǔ)言實(shí)現(xiàn),例如Java,.Net Framework語(yǔ)言. 在第3節(jié)和第4節(jié),我們將以兩個(gè)分別使用靜態(tài)過(guò)程語(yǔ)言和已有動(dòng)態(tài)編程語(yǔ)言的開(kāi)源數(shù)據(jù)庫(kù)中存儲(chǔ)過(guò)程的實(shí)現(xiàn)來(lái)分別分析這兩類(lèi)實(shí)現(xiàn)方案.

    2 存儲(chǔ)過(guò)程支持的主要功能

    存儲(chǔ)過(guò)程是一段運(yùn)行在數(shù)據(jù)庫(kù)端的程序代碼,能夠被數(shù)據(jù)庫(kù)系統(tǒng)動(dòng)態(tài)地加載,編譯和執(zhí)行. 它支持?jǐn)?shù)據(jù)庫(kù)訪問(wèn),變量定義,流程控制等功能. 一個(gè)數(shù)據(jù)庫(kù)管理系統(tǒng)如果需要實(shí)現(xiàn)存儲(chǔ)過(guò)程功能,需要考慮以下幾個(gè)問(wèn)題.

    2.1 基本語(yǔ)法

    存儲(chǔ)過(guò)程需要支持的功能主要包括,變量聲明、變量賦值、表達(dá)式計(jì)算、流程控制以及SQL語(yǔ)句執(zhí)行,當(dāng)然,也需要包括為了解決數(shù)據(jù)庫(kù)和程序設(shè)計(jì)語(yǔ)言之間阻抗不匹配而引入的游標(biāo). 下面將對(duì)以上功能進(jìn)行逐一闡述.

    變量聲明 存儲(chǔ)過(guò)程支持的變量包括數(shù)據(jù)庫(kù)本身支持的變量類(lèi)型,以及表的行記錄,游標(biāo)等. 例如integer,numeric(5,2),varchar,tablename%ROWTYPE和cursor等. 在執(zhí)行存儲(chǔ)過(guò)程時(shí),變量的取值,變量的類(lèi)型等信息需要存儲(chǔ)在過(guò)程的執(zhí)行上下文中.

    代碼塊定義 代碼塊可以用于邏輯分組或者把變量局部化為作用于一個(gè)比較小的語(yǔ)句組,在塊內(nèi)能定義臨時(shí)變量,執(zhí)行若干語(yǔ)句等.

    表達(dá)式計(jì)算表達(dá)式計(jì)算需要處理包含常量和變量的表達(dá)式,需要產(chǎn)生正確的結(jié)果及結(jié)果類(lèi)型. 表達(dá)式計(jì)算可以有單獨(dú)的功能模塊支持,也可以直接繼承數(shù)據(jù)庫(kù)提供的表達(dá)式計(jì)算功能.

    變量賦值 變量賦值要求除了能夠處理一般的數(shù)據(jù)類(lèi)型,例如integer, varchar等,同時(shí)也要支持復(fù)合類(lèi)型的賦值,如關(guān)系表中的行記錄. 當(dāng)然,變量賦值也應(yīng)支持?jǐn)?shù)據(jù)庫(kù)中特有的游標(biāo)類(lèi)型的賦值.

    流程控制 流程控制是提供編寫(xiě)復(fù)雜的業(yè)務(wù)邏輯所必須的功能. 主要包括條件語(yǔ)句、循環(huán)語(yǔ)句以及過(guò)程返回語(yǔ)句. 其中,循環(huán)語(yǔ)句需要支持對(duì)關(guān)系表記錄的迭代.

    數(shù)據(jù)庫(kù)訪問(wèn) 其中包括執(zhí)行SQL語(yǔ)句,使用游標(biāo)等. 在這個(gè)模塊,存儲(chǔ)過(guò)程需要能夠向主數(shù)據(jù)庫(kù)引擎提交SQL查詢,緩存SQL解析后的執(zhí)行計(jì)劃,定義和使用游標(biāo),將查詢結(jié)果存儲(chǔ)到變量中. 這個(gè)模塊通常需要設(shè)計(jì)數(shù)據(jù)庫(kù)的內(nèi)部接口,供服務(wù)器端編程使用.

    2.2 過(guò)程編譯、執(zhí)行與存儲(chǔ)

    存儲(chǔ)過(guò)程的編譯[6]發(fā)生在過(guò)程初次編譯階段和過(guò)程執(zhí)行階段. 這兩部分工作分別是由過(guò)程編譯模塊和SQL編譯模塊完成. 前者主要負(fù)責(zé)諸如變量定義賦值,流程控制等內(nèi)容的編譯工作,而后者負(fù)責(zé)SQL語(yǔ)句的編譯工作. 通常,這部分工作是在存儲(chǔ)過(guò)程被首次調(diào)用時(shí)完成的. 例如當(dāng)首次執(zhí)行SQL語(yǔ)句時(shí),數(shù)據(jù)庫(kù)內(nèi)核會(huì)完成對(duì)SQL的解析,并產(chǎn)生執(zhí)行計(jì)劃. 這部分編譯結(jié)果會(huì)由存儲(chǔ)過(guò)程模塊緩存.

    過(guò)程的執(zhí)行同樣可以分為兩個(gè)部分:(1)由存儲(chǔ)過(guò)程模塊執(zhí)行的語(yǔ)句;(2)由數(shù)據(jù)庫(kù)引擎執(zhí)行的語(yǔ)句. 前者需要定義和實(shí)現(xiàn)每類(lèi)語(yǔ)句的執(zhí)行函數(shù),完成語(yǔ)句的執(zhí)行. 后者需要定義訪問(wèn)數(shù)據(jù)庫(kù)的接口,通過(guò)訪問(wèn)接口來(lái)完成語(yǔ)句執(zhí)行. 返回的結(jié)果需要復(fù)制到存儲(chǔ)過(guò)程模塊執(zhí)行的上下文中,并交由該模塊進(jìn)行下一步的處理.

    與保存在數(shù)據(jù)庫(kù)中其他信息一樣,數(shù)據(jù)庫(kù)管理系統(tǒng)也要保證存儲(chǔ)過(guò)程在系統(tǒng)故障恢復(fù)后,依然可以正常使用. 因此,如何將過(guò)程序列化到非易失性存儲(chǔ)器尤為重要. 根據(jù)采用的過(guò)程語(yǔ)言類(lèi)型,當(dāng)前主要有兩種存儲(chǔ)方案. 其中,第一種方案是,存儲(chǔ)過(guò)程的源代碼會(huì)存儲(chǔ)在系統(tǒng)表中,編譯后的目標(biāo)代碼存儲(chǔ)在系統(tǒng)緩存中. 第二種方案是,在系統(tǒng)表中只記錄存儲(chǔ)過(guò)程的調(diào)用信息,例如過(guò)程名,參數(shù)信息等,而不存儲(chǔ)過(guò)程源代碼,編譯后的結(jié)果存儲(chǔ)在系統(tǒng)外部,當(dāng)需要調(diào)用時(shí),系統(tǒng)根據(jù)存儲(chǔ)路徑加載,并在系統(tǒng)內(nèi)部緩存.

    在下一節(jié)中,我們將以PostgreSQL為例,重點(diǎn)介紹設(shè)計(jì)自定義過(guò)程語(yǔ)言實(shí)現(xiàn)存儲(chǔ)過(guò)程模塊的機(jī)制.

    3 靜態(tài)語(yǔ)言存儲(chǔ)過(guò)程實(shí)現(xiàn)機(jī)制

    PostgreSQL[5,7]是一個(gè)自由的對(duì)象-關(guān)系數(shù)據(jù)庫(kù)服務(wù)器(數(shù)據(jù)庫(kù)管理系統(tǒng)),它在靈活的 BSD-風(fēng)格許可證下發(fā)行. 它提供了相對(duì)其他開(kāi)放源代碼數(shù)據(jù)庫(kù)系統(tǒng)(比如 MySQL 和 Firebird),和專(zhuān)有商用系統(tǒng)(比如 Oracle、Sybase、IBM 的 DB2 和 Microsoft SQL Server)之外的另一種選擇.

    PostgreSQL雖然支持使用內(nèi)置過(guò)程語(yǔ)言PL/pgSQL、腳本語(yǔ)言、編譯語(yǔ)言C和C++等編寫(xiě)存儲(chǔ)過(guò)程. 但本節(jié)重點(diǎn)以PostgreSQL為例,闡述靜態(tài)語(yǔ)言存儲(chǔ)過(guò)程實(shí)現(xiàn)的原理和機(jī)制.

    3.1 PL/pgSQL簡(jiǎn)介

    PL/pgSQL是PostgreSQL數(shù)據(jù)庫(kù)系統(tǒng)的一個(gè)可裝載的過(guò)程語(yǔ)言,其語(yǔ)法類(lèi)似于Oracle的PL/SQL. PL/pgSQL的設(shè)計(jì)目標(biāo)是創(chuàng)建一種可裝載的過(guò)程語(yǔ)言:(1)可用于創(chuàng)建函數(shù)和觸發(fā)器過(guò)程;(2)為 SQL 語(yǔ)言增加控制結(jié)構(gòu);(3)可以執(zhí)行復(fù)雜的計(jì)算; (4)繼承所有用戶定義類(lèi)型,函數(shù)和操作符.

    為了支持PL/pgSQL,Postgre需要提供該過(guò)程語(yǔ)言的編譯功能、執(zhí)行功能、存儲(chǔ)和數(shù)據(jù)庫(kù)訪問(wèn)功能.

    3.2 編譯與執(zhí)行

    3.2.1 詞法解析與語(yǔ)法解析

    在存儲(chǔ)過(guò)程的編譯階段需要將過(guò)程源代碼編譯為系統(tǒng)內(nèi)部指令樹(shù). 但需要注意的是,在函數(shù)內(nèi)使用到的獨(dú)立的SQL 表達(dá)式和 SQL 命令的編譯則是在過(guò)程首次調(diào)用階段完成,其由PostgreSQL的SQL解析模塊負(fù)責(zé)編譯,并產(chǎn)生執(zhí)行計(jì)劃.

    正如傳統(tǒng)的SQL一樣,對(duì)過(guò)程源碼的編譯也需要經(jīng)過(guò)詞法解析和語(yǔ)法解析. 在PostgreSQL中采用開(kāi)源軟件Flex與Bison完成詞法解析與語(yǔ)法解析. Flex進(jìn)行詞法分析,這需要我們?cè)O(shè)計(jì)過(guò)程語(yǔ)言的語(yǔ)法后,為其設(shè)計(jì)正則表達(dá)式來(lái)匹配源碼中出現(xiàn)的標(biāo)記(常量,數(shù)學(xué)符號(hào),括號(hào),中括號(hào),變量名,保留字等),并定義規(guī)則將標(biāo)記映射為內(nèi)部標(biāo)志符. 之后,Bison來(lái)對(duì)詞法分析后的內(nèi)部標(biāo)志符序列進(jìn)行語(yǔ)法分析,形成抽象語(yǔ)義樹(shù). 我們需要為每個(gè)語(yǔ)義單元設(shè)計(jì)識(shí)別規(guī)則,并為其創(chuàng)建一個(gè)相應(yīng)的結(jié)構(gòu)保存.

    3.2.2 過(guò)程執(zhí)行

    過(guò)程的執(zhí)行實(shí)際上是一個(gè)遍歷語(yǔ)法樹(shù)的過(guò)程,根據(jù)當(dāng)前訪問(wèn)的指令,轉(zhuǎn)到對(duì)應(yīng)的指令函數(shù)進(jìn)行執(zhí)行. 圖1以IF語(yǔ)句為例,來(lái)說(shuō)明這個(gè)過(guò)程.

    圖1 IF語(yǔ)句的指令函數(shù)

    對(duì)于每個(gè)語(yǔ)法樹(shù)中的節(jié)點(diǎn),均有一個(gè)對(duì)應(yīng)的指令函數(shù)負(fù)責(zé)該指令的解釋運(yùn)行. 整個(gè)過(guò)程的執(zhí)行是從指令樹(shù)的根節(jié)點(diǎn)開(kāi)始遍歷,并在運(yùn)行時(shí)決定執(zhí)行的路徑.

    3.2.3 數(shù)據(jù)庫(kù)訪問(wèn)

    在PostgreSQL中,對(duì)于需要訪問(wèn)數(shù)據(jù)庫(kù)的指令,指令函數(shù)需要訪問(wèn)系統(tǒng)提供的內(nèi)部訪問(wèn)接口來(lái)完成數(shù)據(jù)庫(kù)訪問(wèn)操作,例如,執(zhí)行一條查詢語(yǔ)句、插入數(shù)據(jù)或者計(jì)算某個(gè)表達(dá)式的結(jié)果. 在PostgreSQL內(nèi)部,提供了服務(wù)端編程接口(Server Programming Interface)來(lái)接收來(lái)自系統(tǒng)內(nèi)部的數(shù)據(jù)操作和訪問(wèn)請(qǐng)求. 在下表中,表2列舉了接口包含的部分重要訪問(wèn)函數(shù):

    表2 SPI訪問(wèn)接口

    3.3 存儲(chǔ)策略

    存儲(chǔ)過(guò)程的存儲(chǔ),即是對(duì)過(guò)程的持久化,要保證過(guò)程在系統(tǒng)重啟后依舊能夠使用. 在PostgreSQL中,過(guò)程存儲(chǔ)分為兩個(gè)部分,過(guò)程的源代碼和編譯后的指令集.

    過(guò)程的源代碼會(huì)被存儲(chǔ)在系統(tǒng)表pg_proc中. 該系統(tǒng)表用于存儲(chǔ)關(guān)于函數(shù)或者過(guò)程的信息. 表3列舉了需要存儲(chǔ)的部分重要屬性. 從表3可以看出,系統(tǒng)表主要存儲(chǔ)了過(guò)程的原始信息,包括名字,源碼,參數(shù),調(diào)用方式等. 由于這些信息是存儲(chǔ)在系統(tǒng)表中的,從而保證了過(guò)程存儲(chǔ)的持久化.

    過(guò)程會(huì)在創(chuàng)建或第一次調(diào)用的時(shí)候被編譯. 編譯后的執(zhí)行計(jì)劃會(huì)被存儲(chǔ)在位于系統(tǒng)緩存中的hash表中. 每個(gè)過(guò)程對(duì)應(yīng)一條記錄,主鍵為根據(jù)過(guò)程名和參數(shù)計(jì)算得到的hash值,映射的對(duì)象是過(guò)程編譯后的指令集.

    對(duì)過(guò)程的調(diào)用,首先會(huì)從系統(tǒng)表中找到對(duì)應(yīng)的過(guò)程記錄,然后在系統(tǒng)緩存中尋找是否存在已編譯的指令集,如果沒(méi)有,那么根據(jù)系統(tǒng)表中的prosrc字段重新編譯,并存儲(chǔ)到系統(tǒng)緩存中.

    表3 pg_proc表的部分重要屬性

    3.3 靜態(tài)語(yǔ)言實(shí)現(xiàn)存儲(chǔ)過(guò)程小結(jié)

    PostgreSQL采用的存儲(chǔ)過(guò)程實(shí)現(xiàn)方式是定制了自己的過(guò)程語(yǔ)言PL/pgSQL,在系統(tǒng)內(nèi)部實(shí)現(xiàn)過(guò)程的編譯、運(yùn)行和存儲(chǔ). 這種策略的主要工作事實(shí)上可以分為兩個(gè)部分:(1)提供過(guò)程語(yǔ)言的編譯和運(yùn)行機(jī)制;(2)設(shè)計(jì)過(guò)程語(yǔ)言訪問(wèn)數(shù)據(jù)庫(kù)系統(tǒng)的接口. 而大量的工作在于提供過(guò)程語(yǔ)言的基本功能. 在下一節(jié)中,我們將介紹一種更為簡(jiǎn)明的,利用動(dòng)態(tài)語(yǔ)言中的反射機(jī)制來(lái)實(shí)現(xiàn)存儲(chǔ)過(guò)程的策略.

    4 動(dòng)態(tài)語(yǔ)言存儲(chǔ)過(guò)程實(shí)現(xiàn)機(jī)制

    VoltDB[8,9]是一個(gè)內(nèi)存數(shù)據(jù)庫(kù)[10],提供了 NoSQL 數(shù)據(jù)庫(kù)的可伸縮性和傳統(tǒng)關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)的 ACID 一致性. 使用 Java編寫(xiě)的存儲(chǔ)過(guò)程進(jìn)行數(shù)據(jù)操作. 我們以VoltDB系統(tǒng)為例來(lái)闡述使用動(dòng)態(tài)語(yǔ)言來(lái)實(shí)現(xiàn)存儲(chǔ)過(guò)程的原理,VoltDB在上層采用的是Java語(yǔ)言開(kāi)發(fā),負(fù)責(zé)系統(tǒng)的集群管理,事務(wù)調(diào)度,SQL解析,接受客戶端連接等功能;下層采用的C++語(yǔ)言開(kāi)發(fā),負(fù)責(zé)SQL的執(zhí)行和數(shù)據(jù)的存取. 存儲(chǔ)過(guò)程實(shí)現(xiàn)在Java層.

    4.1 反射機(jī)制

    從效果來(lái)看,存儲(chǔ)過(guò)程是一段動(dòng)態(tài)添加到系統(tǒng)中執(zhí)行的代碼. 而Java提供的反射機(jī)制具備這樣的功能. 反射機(jī)制允許Java在運(yùn)行時(shí)加載、探知、使用編譯期間完全未知的類(lèi). Java可以加載一個(gè)運(yùn)行時(shí)才得知名稱(chēng)的類(lèi),獲悉其完整構(gòu)造,并生成對(duì)象實(shí)體、或修改成員變量,或調(diào)用方法.

    VoltDB利用該機(jī)制,為應(yīng)用程序提供了可擴(kuò)展的編程接口,應(yīng)用程序員通過(guò)繼承系統(tǒng)提供的過(guò)程基類(lèi),定制應(yīng)用訪問(wèn)數(shù)據(jù)庫(kù)的邏輯,并在系統(tǒng)外部使用Java編譯器進(jìn)行編譯,并最終交由系統(tǒng)在運(yùn)行時(shí)加載和調(diào)用.

    4.2 過(guò)程的編譯與執(zhí)行

    VoltDB中存儲(chǔ)過(guò)程的流程控制,變量定義等功能完全由Java提供,而對(duì)于需要訪問(wèn)數(shù)據(jù)庫(kù)的操作,設(shè)計(jì)了相應(yīng)的接口. 每一個(gè)存儲(chǔ)過(guò)程都需要繼承這個(gè)接口,并使用相應(yīng)的接口方法來(lái)提交查詢,獲得結(jié)果.

    下面我們給出一個(gè)VoltDB中存儲(chǔ)過(guò)程的樣例.

    public class KvUdpate extends VoltProcedure {

    public final SQLStmtaddRecord = new SQLStmt

    “insert into kvstore values(?,?);”

    );

    publicVoltTable[] run(int a, int b) throws Exception{

    voltQueueSQL(addRecord, a, b);

    voltExecuteSQL(true);

    return null;

    }

    }

    這段代碼會(huì)被Java編譯器編譯. 例如:

    $javac -cp $“CLASSPATH:/opt/voltdb/voltdb/*”UpdatePeople.java

    這里Java編譯器只負(fù)責(zé)編譯Java語(yǔ)法相關(guān)的內(nèi)容. 而對(duì)于SQL語(yǔ)句是由VoltDB的SQL解析引擎在過(guò)程調(diào)用時(shí)負(fù)責(zé)編譯和緩存.

    VoltProcedure主要提供了如表4所示的接口函數(shù):

    表4 VoltProcedure主要接口函數(shù)

    需要注意的是,在VoltProcedure中并沒(méi)有提供游標(biāo)等功能,對(duì)表的迭代訪問(wèn)是使用VoltTable提供的相應(yīng)操作方法. 編譯與執(zhí)行的整體框架如圖2所示.

    圖2 VoltDB存儲(chǔ)過(guò)程框架

    4.3 過(guò)程的存儲(chǔ)

    存儲(chǔ)過(guò)程采用Java編寫(xiě),在系統(tǒng)外進(jìn)行編譯和存儲(chǔ),關(guān)于過(guò)程的信息,例如過(guò)程名,參數(shù),使用的SQL語(yǔ)句會(huì)被存儲(chǔ)在系統(tǒng)表中. 在外部的類(lèi)文件被調(diào)用后,系統(tǒng)內(nèi)部會(huì)緩存類(lèi)信息,已備下一次的調(diào)用.

    編譯后的存儲(chǔ)過(guò)程會(huì)在系統(tǒng)表中進(jìn)行注冊(cè). 例如:

    CREATE PROCEDURE FROM CLASS UpdatePeople;

    PARTITION PROCEDURE UpdatePeople ON TABLE people COLUMN state_num;

    運(yùn)行以上的命令后,系統(tǒng)表中就記錄了這個(gè)過(guò)程的相關(guān)信息,從而方便之后的再調(diào)用. VoltDB對(duì)過(guò)程的調(diào)用是通過(guò)系統(tǒng)表中提供的過(guò)程名和相應(yīng)的存儲(chǔ)路徑,并據(jù)此,從外部加載相應(yīng)的類(lèi),通過(guò)反射機(jī)制生成該類(lèi)的實(shí)例,調(diào)用相應(yīng)的run()方法.

    4.4 支持反射的動(dòng)態(tài)語(yǔ)言實(shí)現(xiàn)存儲(chǔ)過(guò)程小結(jié)

    利用動(dòng)態(tài)語(yǔ)言(例如,Java)的反射機(jī)制能夠非常便捷地實(shí)現(xiàn)存儲(chǔ)過(guò)程. 它不需要實(shí)現(xiàn)存儲(chǔ)過(guò)程的編譯和執(zhí)行,從而大大降低了開(kāi)發(fā)難度. 然而,這取決于底層數(shù)據(jù)庫(kù)采用的實(shí)現(xiàn)語(yǔ)言是否能夠提供反射機(jī)制,因而已有利用的動(dòng)態(tài)語(yǔ)言來(lái)實(shí)現(xiàn)存儲(chǔ)過(guò)程有一定的局限性.

    5 OceanBase中的實(shí)現(xiàn)思路

    OceanBase[3,4]是阿里集團(tuán)研發(fā)的可擴(kuò)展的關(guān)系數(shù)據(jù)庫(kù). 目前的版本暫時(shí)不支持存儲(chǔ)過(guò)程的編寫(xiě),本小節(jié)我們將探討在OceanBase中添加存儲(chǔ)過(guò)程模塊的關(guān)鍵技術(shù). OceanBase整機(jī)架構(gòu)分為四個(gè)模塊:主控服務(wù)器RootServer,更新服務(wù)器UpdateServer,基線數(shù)據(jù)服務(wù)器ChunkServer以及合并服務(wù)器MergeServer.

    ◆ 客戶端:用戶使用OB的方式和MySQL數(shù)據(jù)庫(kù)完全相同,支持JDBC、C客戶端訪問(wèn).

    ◆ RootServer: 管理集群中的所有服務(wù)器,Tablet數(shù)據(jù)分布以及副本管理. RootServer一般為一主一備,主備之間數(shù)據(jù)強(qiáng)同步.

    ◆ UpdateServer:存儲(chǔ)OB系統(tǒng)的增量更新數(shù)據(jù). UpdateServer一般為一主一備,UpdateServer和RootServer一般部署在同一服務(wù)器中.

    ◆ ChunkServer:存儲(chǔ)OB系統(tǒng)的基線數(shù)據(jù). 基準(zhǔn)數(shù)據(jù)一般存儲(chǔ)兩份或者三份.

    ◆ MergeServer:接收并解析用戶的SQL請(qǐng)求,經(jīng)過(guò)詞法分析、語(yǔ)法分析、查詢優(yōu)化等一系列操作后轉(zhuǎn)發(fā)給相應(yīng)的ChunkServer. 如果請(qǐng)求數(shù)據(jù)分布在多臺(tái)ChunkServer上,MergeServer還需對(duì)多臺(tái)ChunkServer返回的結(jié)果進(jìn)行合并.

    圖3 OceanBase架構(gòu)

    正如之前所討論的,存儲(chǔ)過(guò)程的模塊的編寫(xiě)主要有以PostgreSQL為代表的靜態(tài)語(yǔ)言過(guò)程語(yǔ)言的方式,以及以VoltDB為代表的基于動(dòng)態(tài)語(yǔ)言反射機(jī)制的方式.

    由于OceanBase是采用C++語(yǔ)言開(kāi)發(fā)的,所以實(shí)現(xiàn)存儲(chǔ)過(guò)程的策略主要參考Postgre的實(shí)現(xiàn)方案. MergerServer是OB查詢的入口,因而存儲(chǔ)過(guò)程實(shí)現(xiàn)在MergeServer上. 添加存儲(chǔ)過(guò)程模塊,需要增加存儲(chǔ)過(guò)程編譯模塊,存儲(chǔ)過(guò)程執(zhí)行模塊,Obsql對(duì)存儲(chǔ)過(guò)程定義和調(diào)用的支持以及存儲(chǔ)過(guò)程訪問(wèn)SQL引擎的接口,其基本框架如圖4所示:

    圖4 存儲(chǔ)過(guò)程基本框架設(shè)計(jì)

    ? 定義存儲(chǔ)過(guò)程的指令首先被MergerServer接收,MergerServer調(diào)用SQL詞法語(yǔ)法解析模塊,對(duì)過(guò)程定義的部分會(huì)轉(zhuǎn)到存儲(chǔ)過(guò)程的編譯模塊完成.

    ? 編譯后的結(jié)果可以緩存在系統(tǒng)內(nèi)部,過(guò)程源代碼可以存儲(chǔ)在系統(tǒng)表中.

    ? 調(diào)用一個(gè)存儲(chǔ)過(guò)程通過(guò)SQL查詢的入口點(diǎn),轉(zhuǎn)到存儲(chǔ)過(guò)程的執(zhí)行模塊,當(dāng)遇到需要訪問(wèn)數(shù)據(jù)庫(kù)的操作時(shí),通過(guò)訪問(wèn)接口調(diào)用SQL引擎的編譯或者執(zhí)行模塊.

    在MergeServer上,需要封裝存儲(chǔ)過(guò)程訪問(wèn)SQL引擎的訪問(wèn)接口. 該接口需要提供如表5所示的基本訪問(wèn)功能.

    表5 OceanBase的服務(wù)端編程接口需要的基本功能

    6 總 結(jié)

    存儲(chǔ)過(guò)程是用戶使用數(shù)據(jù)庫(kù)的重要功能. 它大大改善了前臺(tái)應(yīng)用訪問(wèn)數(shù)據(jù)庫(kù)的性能. 現(xiàn)有的主流數(shù)據(jù)庫(kù)都支持這項(xiàng)功能. 存儲(chǔ)過(guò)程的實(shí)現(xiàn)方案主要取決于數(shù)據(jù)庫(kù)系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn)方案. 本文主要闡述了基于靜態(tài)語(yǔ)言和基于動(dòng)態(tài)語(yǔ)言的反射機(jī)制實(shí)現(xiàn)存儲(chǔ)過(guò)程的基本原理. 并進(jìn)一步以采用C開(kāi)發(fā)的PostgreSQL和以Java開(kāi)發(fā)的VoltDB為例,主要討論了存儲(chǔ)過(guò)程在不同系統(tǒng)中的實(shí)現(xiàn)原理. 最后,對(duì)OceanBase中實(shí)現(xiàn)存儲(chǔ)過(guò)程這項(xiàng)功能給出了初步的設(shè)計(jì).

    [1] Stored Procedure[EB/OL]. http://en.wikipedia.org/wiki/Stored_procedure.

    [2] PL/pgSQL[EB/OL]. http://www.postgresql.org/docs/8.3/static/plpgsql.html.

    [3] OceanBase[EB/OL]. http://alibaba.github.io/oceanbase/.

    [4] 楊傳輝. 大規(guī)模分布式存儲(chǔ)系統(tǒng)原理解析與架構(gòu)實(shí)戰(zhàn)[M]. 北京:工業(yè)出版社,2013.

    [5] 彭智勇,彭煜瑋. PostgreSQL數(shù)據(jù)庫(kù)內(nèi)核分析[M]. 北京:機(jī)械工業(yè)出版社華章公司,2012.

    [6] AHO A V, ULLMAN J D. Principles of Compiler Design[M]. [s.L.]:Addison-Wesley, 1977.

    [7] STONEBRAKER M, KEMNITZ G. The Postgres Next Generation Database Management System[J]. Commun ACM, 1991, 34(10): 78-92.

    [8] KALLMAN R, KIMURA H, NATKINS J, et al. Abadi: H-store: a high-performance, distributed main memory transaction processing system[J]. PVLDB, 2008,1(2): 1496-1499.

    [9] STONEBRAKER M, WEISBERG A. The VoltDB Main Memory DBMS[J]. IEEE Data Eng Bull, 2013, 36(2): 21-27.

    [10] STONNEBRAKER M, MADDEN S, ABADI D J, et al. The end of an Architectural Era: (It’s Time for a Complete Rewrite)[C]//VLDB ’07: Proceedings of the 33rd International Conference on Very Large Data Bases, 2007: 1150-1160.

    (責(zé)任編輯 王善平)

    Study on stored procedure implementation oriented to OceanBase

    ZHU Tao, ZHOU Min-qi, ZHANG Zhao

    (SoftwareEngineerInstitute,EastChinaNormalUniversity,Shanghai200062,China)

    A stored procedure is a pre-compiled subroutine stored in database server, which improves the efficiency of applications’ database access. This paper discussed the implementation of stored procedure based on both static language and dynamic language. Besides, we gave a primary design for implementing stored procedures in OceanBase.

    stored procedure; database system; SQL

    1000-5641(2014)05-0281-09

    2014-07

    國(guó)家自然科學(xué)基金(12345678);上海市重點(diǎn)學(xué)科建設(shè)項(xiàng)目(98776654)

    朱濤,男,博士研究生,研究方向?yàn)閮?nèi)存數(shù)據(jù)庫(kù),分布式系統(tǒng). E-mail:zhutaojs@gmail.com.

    周敏奇,男,副教授,碩士生導(dǎo)師,研究方向?yàn)閮?nèi)存數(shù)據(jù)庫(kù). E-mail:mqzhou@sei.ecnu.edu.cn.

    TP392

    A

    10.3969/j.issn.1000-5641.2014.05.025

    猜你喜歡
    數(shù)據(jù)庫(kù)語(yǔ)言系統(tǒng)
    Smartflower POP 一體式光伏系統(tǒng)
    WJ-700無(wú)人機(jī)系統(tǒng)
    ZC系列無(wú)人機(jī)遙感系統(tǒng)
    語(yǔ)言是刀
    文苑(2020年4期)2020-05-30 12:35:30
    讓語(yǔ)言描寫(xiě)搖曳多姿
    連通與提升系統(tǒng)的最后一塊拼圖 Audiolab 傲立 M-DAC mini
    數(shù)據(jù)庫(kù)
    累積動(dòng)態(tài)分析下的同聲傳譯語(yǔ)言壓縮
    數(shù)據(jù)庫(kù)
    數(shù)據(jù)庫(kù)
    欧美国产精品一级二级三级 | 日韩av在线免费看完整版不卡| 亚洲不卡免费看| 成人无遮挡网站| 搡老乐熟女国产| 精华霜和精华液先用哪个| 亚洲精品乱码久久久久久按摩| 国产熟女欧美一区二区| 国产淫语在线视频| 亚洲精品乱码久久久久久按摩| 男女无遮挡免费网站观看| 青春草国产在线视频| 91精品伊人久久大香线蕉| 又粗又硬又长又爽又黄的视频| 国产伦精品一区二区三区视频9| 人妻夜夜爽99麻豆av| 另类亚洲欧美激情| av在线老鸭窝| 国产精品国产三级国产专区5o| 91精品伊人久久大香线蕉| 大片电影免费在线观看免费| 精品国产三级普通话版| 亚洲天堂av无毛| 国产乱人视频| 网址你懂的国产日韩在线| 赤兔流量卡办理| 日韩电影二区| 久久精品国产a三级三级三级| 亚洲欧美日韩另类电影网站 | 国产乱人视频| 人妻一区二区av| av线在线观看网站| 人妻系列 视频| 国产精品熟女久久久久浪| 欧美日韩视频高清一区二区三区二| 亚洲av成人精品一二三区| 亚洲精品乱码久久久久久按摩| 边亲边吃奶的免费视频| 欧美区成人在线视频| 免费大片黄手机在线观看| 另类亚洲欧美激情| 日韩成人伦理影院| 80岁老熟妇乱子伦牲交| 亚洲天堂国产精品一区在线| 香蕉精品网在线| 免费黄色在线免费观看| 亚洲最大成人手机在线| 男插女下体视频免费在线播放| 国语对白做爰xxxⅹ性视频网站| 国模一区二区三区四区视频| 亚洲怡红院男人天堂| 日韩人妻高清精品专区| 久久女婷五月综合色啪小说 | 大香蕉久久网| 国产精品.久久久| 久久鲁丝午夜福利片| 成年版毛片免费区| 色网站视频免费| 交换朋友夫妻互换小说| av在线观看视频网站免费| 成人鲁丝片一二三区免费| 搡老乐熟女国产| 国产精品爽爽va在线观看网站| 舔av片在线| 日本爱情动作片www.在线观看| 久久韩国三级中文字幕| 高清欧美精品videossex| 禁无遮挡网站| 免费大片18禁| 五月伊人婷婷丁香| 亚洲av二区三区四区| 熟女av电影| 国产淫语在线视频| 国产在线一区二区三区精| 超碰97精品在线观看| 韩国av在线不卡| 国产成人aa在线观看| 一本久久精品| 啦啦啦啦在线视频资源| 香蕉精品网在线| 最后的刺客免费高清国语| 国产黄片视频在线免费观看| 国产精品三级大全| 97超视频在线观看视频| 精品国产三级普通话版| 精品人妻视频免费看| av网站免费在线观看视频| 精品国产露脸久久av麻豆| 国产精品不卡视频一区二区| 新久久久久国产一级毛片| 亚洲av不卡在线观看| 一级黄片播放器| 精品人妻熟女av久视频| 天天躁日日操中文字幕| 久久午夜福利片| 亚洲欧洲日产国产| 国产精品人妻久久久影院| 国产伦精品一区二区三区视频9| 精品人妻视频免费看| 蜜臀久久99精品久久宅男| 国产高潮美女av| 夜夜看夜夜爽夜夜摸| 国产精品.久久久| 亚洲国产日韩一区二区| 伦精品一区二区三区| 国产精品国产av在线观看| 国产免费又黄又爽又色| 亚洲精品一区蜜桃| 午夜免费男女啪啪视频观看| 联通29元200g的流量卡| 97超碰精品成人国产| 人妻制服诱惑在线中文字幕| 看十八女毛片水多多多| 成人亚洲欧美一区二区av| 国产男女超爽视频在线观看| 老司机影院毛片| 99久久九九国产精品国产免费| 亚洲最大成人中文| 久久久久国产网址| 高清视频免费观看一区二区| 国产伦在线观看视频一区| 亚洲国产日韩一区二区| 亚洲av二区三区四区| 久久久久久久久久人人人人人人| 人人妻人人澡人人爽人人夜夜| 欧美激情久久久久久爽电影| 少妇高潮的动态图| 看十八女毛片水多多多| 日韩国内少妇激情av| 国产白丝娇喘喷水9色精品| 久久精品国产亚洲av涩爱| 人妻 亚洲 视频| 亚洲av成人精品一区久久| 午夜精品一区二区三区免费看| 老师上课跳d突然被开到最大视频| 精品99又大又爽又粗少妇毛片| 极品教师在线视频| 超碰97精品在线观看| 又爽又黄无遮挡网站| 欧美高清性xxxxhd video| 成年av动漫网址| 涩涩av久久男人的天堂| 日韩视频在线欧美| 亚洲av成人精品一区久久| 免费看不卡的av| 国产伦在线观看视频一区| 亚洲成色77777| 国产免费一级a男人的天堂| 国产av码专区亚洲av| 网址你懂的国产日韩在线| 国产白丝娇喘喷水9色精品| 亚洲欧美日韩无卡精品| 日韩人妻高清精品专区| 男人舔奶头视频| 国产免费一级a男人的天堂| 婷婷色麻豆天堂久久| 少妇被粗大猛烈的视频| 色哟哟·www| 超碰av人人做人人爽久久| 精品久久久精品久久久| 99久国产av精品国产电影| 亚洲综合精品二区| 国内精品宾馆在线| 国产人妻一区二区三区在| 亚洲国产精品成人久久小说| 国产精品一区www在线观看| 99热6这里只有精品| 热re99久久精品国产66热6| 国产精品蜜桃在线观看| 成年av动漫网址| videos熟女内射| 亚洲av成人精品一区久久| 精品视频人人做人人爽| 人妻 亚洲 视频| 少妇的逼水好多| 日韩在线高清观看一区二区三区| 欧美变态另类bdsm刘玥| 人妻一区二区av| av天堂中文字幕网| 免费看a级黄色片| 亚洲精品乱久久久久久| 少妇的逼好多水| 高清av免费在线| 97在线视频观看| 女人十人毛片免费观看3o分钟| 少妇人妻精品综合一区二区| 在线免费观看不下载黄p国产| 国产精品久久久久久久久免| 国产欧美日韩一区二区三区在线 | 最后的刺客免费高清国语| 中文乱码字字幕精品一区二区三区| 三级国产精品片| 18禁动态无遮挡网站| 美女被艹到高潮喷水动态| 人人妻人人爽人人添夜夜欢视频 | 自拍偷自拍亚洲精品老妇| 国产午夜精品久久久久久一区二区三区| 又大又黄又爽视频免费| 中文精品一卡2卡3卡4更新| 舔av片在线| 久久97久久精品| 建设人人有责人人尽责人人享有的 | 插逼视频在线观看| 自拍欧美九色日韩亚洲蝌蚪91 | 亚洲电影在线观看av| 精品人妻视频免费看| www.色视频.com| 国产欧美另类精品又又久久亚洲欧美| 噜噜噜噜噜久久久久久91| 国内精品宾馆在线| 国产精品久久久久久精品古装| 精品久久久久久久人妻蜜臀av| 日本免费在线观看一区| 3wmmmm亚洲av在线观看| 国产欧美另类精品又又久久亚洲欧美| 久久99热这里只频精品6学生| 乱系列少妇在线播放| 成人美女网站在线观看视频| av福利片在线观看| 欧美bdsm另类| 亚洲av一区综合| 国产黄色视频一区二区在线观看| 国产一区有黄有色的免费视频| 国产欧美日韩精品一区二区| 亚洲在久久综合| 天堂中文最新版在线下载 | 菩萨蛮人人尽说江南好唐韦庄| 一边亲一边摸免费视频| 久久精品综合一区二区三区| 久久精品久久精品一区二区三区| 亚洲va在线va天堂va国产| 国产亚洲av嫩草精品影院| 水蜜桃什么品种好| 成人鲁丝片一二三区免费| 精品人妻一区二区三区麻豆| 精品久久久久久久人妻蜜臀av| 人妻制服诱惑在线中文字幕| 国内精品美女久久久久久| 国产精品福利在线免费观看| 久久久久久久久大av| 97在线视频观看| 毛片一级片免费看久久久久| 亚洲国产精品成人久久小说| 超碰97精品在线观看| 在线观看一区二区三区激情| 国产探花极品一区二区| 亚洲欧美精品自产自拍| 国产真实伦视频高清在线观看| 七月丁香在线播放| 99九九线精品视频在线观看视频| 欧美日韩国产mv在线观看视频 | 大片免费播放器 马上看| 午夜激情福利司机影院| 内地一区二区视频在线| 国产免费又黄又爽又色| 精品酒店卫生间| 午夜福利网站1000一区二区三区| av免费观看日本| 国产精品人妻久久久影院| 欧美日韩视频高清一区二区三区二| 亚洲最大成人手机在线| 国产爽快片一区二区三区| 日本熟妇午夜| 亚洲精品视频女| 久久久久精品久久久久真实原创| 成人漫画全彩无遮挡| 午夜爱爱视频在线播放| av黄色大香蕉| 亚洲色图av天堂| 黄片无遮挡物在线观看| 国产黄a三级三级三级人| 午夜福利视频精品| 三级国产精品片| 亚洲丝袜综合中文字幕| 色网站视频免费| 看非洲黑人一级黄片| 中国国产av一级| 亚洲国产色片| 涩涩av久久男人的天堂| 国产白丝娇喘喷水9色精品| 久久国产乱子免费精品| 日本猛色少妇xxxxx猛交久久| 中文乱码字字幕精品一区二区三区| 可以在线观看毛片的网站| 永久网站在线| 色吧在线观看| 18禁裸乳无遮挡免费网站照片| 国产一级毛片在线| 熟女av电影| 欧美精品人与动牲交sv欧美| 菩萨蛮人人尽说江南好唐韦庄| 久久精品久久精品一区二区三区| a级毛色黄片| 欧美变态另类bdsm刘玥| 国产精品一区二区性色av| xxx大片免费视频| 2021少妇久久久久久久久久久| 老女人水多毛片| 人体艺术视频欧美日本| 久久久久久伊人网av| 欧美日韩国产mv在线观看视频 | 久久久久国产精品人妻一区二区| videos熟女内射| 欧美最新免费一区二区三区| 久久久亚洲精品成人影院| 99久久中文字幕三级久久日本| 在线观看美女被高潮喷水网站| 日韩 亚洲 欧美在线| 99热这里只有是精品50| 久久久久久久久久久免费av| 99热国产这里只有精品6| 精品少妇久久久久久888优播| 午夜激情福利司机影院| 亚洲人成网站在线观看播放| 麻豆久久精品国产亚洲av| 99热网站在线观看| 亚洲,一卡二卡三卡| 亚洲成人一二三区av| 国产精品不卡视频一区二区| 91午夜精品亚洲一区二区三区| 日韩av免费高清视频| 春色校园在线视频观看| 老师上课跳d突然被开到最大视频| 老司机影院毛片| 一级毛片 在线播放| 婷婷色综合www| 久久久a久久爽久久v久久| 精品熟女少妇av免费看| 一本—道久久a久久精品蜜桃钙片 精品乱码久久久久久99久播 | 少妇高潮的动态图| 男女啪啪激烈高潮av片| 2018国产大陆天天弄谢| 欧美日韩国产mv在线观看视频 | 婷婷色综合www| 国产久久久一区二区三区| 国产成人精品福利久久| 看非洲黑人一级黄片| 观看美女的网站| 国产视频内射| 日韩在线高清观看一区二区三区| 男女啪啪激烈高潮av片| 有码 亚洲区| 在线免费十八禁| 午夜免费观看性视频| 午夜福利高清视频| 国产成人精品婷婷| 亚洲四区av| 青春草视频在线免费观看| 身体一侧抽搐| 五月玫瑰六月丁香| 亚洲国产精品成人久久小说| 久久鲁丝午夜福利片| 大片电影免费在线观看免费| 欧美 日韩 精品 国产| 成年女人看的毛片在线观看| 日韩强制内射视频| 韩国av在线不卡| 欧美激情久久久久久爽电影| 99热国产这里只有精品6| 国语对白做爰xxxⅹ性视频网站| 成人美女网站在线观看视频| 久久热精品热| 欧美性感艳星| 如何舔出高潮| 老司机影院毛片| 成人国产av品久久久| 精品午夜福利在线看| 精品一区二区三区视频在线| 少妇的逼水好多| av国产免费在线观看| 精品久久久精品久久久| 国产欧美日韩一区二区三区在线 | 国产成人a区在线观看| 一级毛片黄色毛片免费观看视频| 一本色道久久久久久精品综合| 日本一二三区视频观看| av线在线观看网站| 成年女人看的毛片在线观看| 亚洲国产欧美在线一区| 下体分泌物呈黄色| 欧美人与善性xxx| av免费观看日本| 69av精品久久久久久| 丝瓜视频免费看黄片| 国产成人精品福利久久| 26uuu在线亚洲综合色| 亚洲精品国产av成人精品| 久久亚洲国产成人精品v| av国产免费在线观看| 精品一区在线观看国产| 日本黄色片子视频| 亚洲av二区三区四区| 国产成人精品婷婷| 最近的中文字幕免费完整| 麻豆成人av视频| 国产精品av视频在线免费观看| 免费观看的影片在线观看| 大又大粗又爽又黄少妇毛片口| freevideosex欧美| 亚洲av电影在线观看一区二区三区 | 青春草国产在线视频| 久久鲁丝午夜福利片| 一本—道久久a久久精品蜜桃钙片 精品乱码久久久久久99久播 | 国产精品伦人一区二区| 国产精品一区二区三区四区免费观看| 免费av毛片视频| 国产 精品1| www.av在线官网国产| 丰满人妻一区二区三区视频av| 麻豆成人午夜福利视频| 欧美+日韩+精品| 亚洲熟女精品中文字幕| 久久99热这里只频精品6学生| 国产v大片淫在线免费观看| 欧美激情久久久久久爽电影| av免费在线看不卡| 中文乱码字字幕精品一区二区三区| 免费黄频网站在线观看国产| 成人毛片60女人毛片免费| 啦啦啦中文免费视频观看日本| 男女无遮挡免费网站观看| 亚洲精品乱码久久久久久按摩| 嫩草影院精品99| 亚洲人成网站在线播| 欧美三级亚洲精品| 亚洲av一区综合| 国产色婷婷99| 国产永久视频网站| 少妇的逼好多水| 黄色视频在线播放观看不卡| 精品视频人人做人人爽| 91午夜精品亚洲一区二区三区| 国产精品精品国产色婷婷| 如何舔出高潮| av天堂中文字幕网| 色吧在线观看| 黄色视频在线播放观看不卡| 日韩成人伦理影院| 日日啪夜夜撸| 亚洲成人av在线免费| 网址你懂的国产日韩在线| 日韩不卡一区二区三区视频在线| 大香蕉97超碰在线| 亚洲欧美成人精品一区二区| 国产精品无大码| 大片免费播放器 马上看| 国产一区有黄有色的免费视频| 国产永久视频网站| 久久人人爽av亚洲精品天堂 | 国产精品熟女久久久久浪| 麻豆成人av视频| 国产成人91sexporn| 99热6这里只有精品| av福利片在线观看| av一本久久久久| 免费黄网站久久成人精品| 久久热精品热| 日韩欧美精品免费久久| 熟女av电影| 国产成人福利小说| 丝瓜视频免费看黄片| 午夜福利高清视频| 亚洲欧美日韩卡通动漫| 极品少妇高潮喷水抽搐| 国产永久视频网站| 啦啦啦中文免费视频观看日本| 国产成人a区在线观看| 婷婷色综合大香蕉| 久久久色成人| 看免费成人av毛片| 有码 亚洲区| 久久精品国产a三级三级三级| 日日啪夜夜撸| 久久国内精品自在自线图片| 亚洲在久久综合| 啦啦啦在线观看免费高清www| 晚上一个人看的免费电影| 成人毛片60女人毛片免费| 最近中文字幕高清免费大全6| 男女无遮挡免费网站观看| 久久国产乱子免费精品| 日韩免费高清中文字幕av| 欧美日本视频| 久久99热这里只有精品18| 亚洲欧美一区二区三区国产| 精品酒店卫生间| 亚洲欧洲日产国产| 国产高清三级在线| 菩萨蛮人人尽说江南好唐韦庄| 成人鲁丝片一二三区免费| 国产熟女欧美一区二区| 深爱激情五月婷婷| 少妇的逼水好多| 国产av不卡久久| 中文在线观看免费www的网站| 视频区图区小说| 麻豆精品久久久久久蜜桃| 亚洲欧美精品自产自拍| 国产成人免费无遮挡视频| 97超碰精品成人国产| 97超视频在线观看视频| 91精品国产九色| 亚洲av欧美aⅴ国产| 久久午夜福利片| 亚洲无线观看免费| 国产成年人精品一区二区| 极品教师在线视频| 国产爱豆传媒在线观看| 国模一区二区三区四区视频| 99久久九九国产精品国产免费| 18禁在线播放成人免费| 中文字幕免费在线视频6| 精品国产乱码久久久久久小说| 成人二区视频| 男人舔奶头视频| 51国产日韩欧美| 欧美精品一区二区大全| av国产久精品久网站免费入址| 日韩成人伦理影院| 亚洲国产av新网站| 国产乱来视频区| 日韩人妻高清精品专区| 搡女人真爽免费视频火全软件| 在现免费观看毛片| 国产免费一级a男人的天堂| 热99国产精品久久久久久7| 欧美三级亚洲精品| 禁无遮挡网站| 寂寞人妻少妇视频99o| 久久久久九九精品影院| 熟女电影av网| 亚洲av免费高清在线观看| 身体一侧抽搐| 大香蕉97超碰在线| 在线看a的网站| 老司机影院成人| 永久免费av网站大全| 国产精品一区www在线观看| 1000部很黄的大片| 亚洲最大成人手机在线| 亚洲国产高清在线一区二区三| 欧美日韩国产mv在线观看视频 | 亚洲人成网站在线观看播放| 大片电影免费在线观看免费| 真实男女啪啪啪动态图| 99久久中文字幕三级久久日本| 高清毛片免费看| 97人妻精品一区二区三区麻豆| 99热6这里只有精品| 欧美精品一区二区大全| 春色校园在线视频观看| 黄色配什么色好看| 麻豆国产97在线/欧美| 亚洲精品一区蜜桃| 免费看a级黄色片| 少妇 在线观看| 1000部很黄的大片| 亚洲国产最新在线播放| 色综合色国产| 欧美日韩视频高清一区二区三区二| 80岁老熟妇乱子伦牲交| 日本午夜av视频| 亚洲av电影在线观看一区二区三区 | 国产男女超爽视频在线观看| 国产黄色视频一区二区在线观看| 成人国产麻豆网| 免费人成在线观看视频色| 亚洲色图综合在线观看| 欧美精品人与动牲交sv欧美| 亚洲美女搞黄在线观看| 一级毛片电影观看| av福利片在线观看| 国产精品一二三区在线看| 亚洲一级一片aⅴ在线观看| 亚洲欧美成人精品一区二区| 国产在视频线精品| 欧美日韩在线观看h| 日韩视频在线欧美| 国产免费视频播放在线视频| 日韩av在线免费看完整版不卡| 亚洲国产精品国产精品| 99九九线精品视频在线观看视频| 精品熟女少妇av免费看| 特大巨黑吊av在线直播| 亚洲欧洲日产国产| 成人亚洲欧美一区二区av| 青春草国产在线视频| 亚州av有码| 日日摸夜夜添夜夜添av毛片| 精品久久久久久久末码| 日本与韩国留学比较| 午夜精品一区二区三区免费看| av免费观看日本| 亚洲丝袜综合中文字幕| 18禁在线无遮挡免费观看视频| 亚洲真实伦在线观看| 在线观看一区二区三区激情| 欧美zozozo另类| 午夜日本视频在线| 极品少妇高潮喷水抽搐| 视频中文字幕在线观看| 边亲边吃奶的免费视频| 女的被弄到高潮叫床怎么办| 丰满乱子伦码专区| 99视频精品全部免费 在线| 亚洲成人一二三区av| 精品久久久久久久久av| 亚洲成色77777| a级毛色黄片| 国产亚洲91精品色在线| 成人亚洲精品一区在线观看 | 中文字幕亚洲精品专区| 国产精品无大码| 麻豆乱淫一区二区| 欧美精品一区二区大全|