1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        一文搞懂什么是事務(wù)

        共 7856字,需瀏覽 16分鐘

         ·

        2020-12-20 15:52

        一文搞懂什么是事務(wù)


        • 一文搞懂什么是事務(wù)

          • 事務(wù)概念

          • 臟讀、不可重復(fù)讀、幻讀

          • 數(shù)據(jù)庫(kù)事務(wù)的隔離級(jí)別

          • Spring事務(wù)傳播行為

          • Spring 事務(wù)的兩種實(shí)現(xiàn)

          • 使用事務(wù)時(shí)需要注意的點(diǎn)

          • 總結(jié)


        事務(wù)概念

        我們要理解下事務(wù)概念:什么是事務(wù)呢?事務(wù)是并發(fā)控制的單位,是用戶定義的一個(gè)操作序列。有四個(gè)特性(ACID):

        • 原子性(Atomicity):事務(wù)是數(shù)據(jù)庫(kù)的邏輯工作單位,事務(wù)中包括的諸操作要么全做,要么全不做。

        • 一致性(Consistency):事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)變到另一個(gè)一致性狀態(tài)。一致性與原子性是密切相關(guān)的。

        • 隔離性(Isolation):一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾。

        • 持續(xù)性/永久性(Durability):一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就應(yīng)該是永久性的。

        以上是書(shū)面解釋,簡(jiǎn)單來(lái)說(shuō)就是把你的操作統(tǒng)一化,要么所有操作都成功,要么就都不成功,如果執(zhí)行中有某一項(xiàng)操作失敗,其之前所有的操作都回滾到未執(zhí)行這一系列操作之前的狀態(tài)。

        臟讀、不可重復(fù)讀、幻讀

        先理解這三種由于并發(fā)訪問(wèn)導(dǎo)致的數(shù)據(jù)讀取問(wèn)題,再理解事務(wù)隔離級(jí)別就簡(jiǎn)單多了。

        臟讀

        A事務(wù)讀取B事務(wù)尚未提交的數(shù)據(jù),此時(shí)如果B事務(wù)發(fā)生錯(cuò)誤并執(zhí)行回滾操作,那么A事務(wù)讀取到的數(shù)據(jù)就是臟數(shù)據(jù)。就好像原本的數(shù)據(jù)比較干凈、純粹,此時(shí)由于B事務(wù)更改了它,這個(gè)數(shù)據(jù)變得不再純粹。這個(gè)時(shí)候A事務(wù)立即讀取了這個(gè)臟數(shù)據(jù),但事務(wù)B良心發(fā)現(xiàn),又用回滾把數(shù)據(jù)恢復(fù)成原來(lái)干凈、純粹的樣子,而事務(wù)A卻什么都不知道,最終結(jié)果就是事務(wù)A讀取了此次的臟數(shù)據(jù),稱為臟讀。

        這種情況常發(fā)生于轉(zhuǎn)賬與取款操作中

        不可重復(fù)讀(前后多次讀取,數(shù)據(jù)內(nèi)容不一致)

        事務(wù)A在執(zhí)行讀取操作,由整個(gè)事務(wù)A比較大,前后讀取同一條數(shù)據(jù)需要經(jīng)歷很長(zhǎng)的時(shí)間 。而在事務(wù)A第一次讀取數(shù)據(jù),比如此時(shí)讀取了小明的年齡為20歲,事務(wù)B執(zhí)行更改操作,將小明的年齡更改為30歲,此時(shí)事務(wù)A第二次讀取到小明的年齡時(shí),發(fā)現(xiàn)其年齡是30歲,和之前的數(shù)據(jù)不一樣了,也就是數(shù)據(jù)不重復(fù)了,系統(tǒng)不可以讀取到重復(fù)的數(shù)據(jù),成為不可重復(fù)讀。

        幻讀(前后多次讀取,數(shù)據(jù)總量不一致)

        事務(wù)A在執(zhí)行讀取操作,需要兩次統(tǒng)計(jì)數(shù)據(jù)的總量,前一次查詢數(shù)據(jù)總量后,此時(shí)事務(wù)B執(zhí)行了新增數(shù)據(jù)的操作并提交后,這個(gè)時(shí)候事務(wù)A讀取的數(shù)據(jù)總量和之前統(tǒng)計(jì)的不一樣,就像產(chǎn)生了幻覺(jué)一樣,平白無(wú)故的多了幾條數(shù)據(jù),成為幻讀。

        小總結(jié):不可重復(fù)讀和幻讀到底有什么區(qū)別?

        (1) 不可重復(fù)讀是讀取了其他事務(wù)更改的數(shù)據(jù),針對(duì)update操作

        解決:使用行級(jí)鎖,鎖定該行,事務(wù)A多次讀取操作完成后才釋放該鎖,這個(gè)時(shí)候才允許其他事務(wù)更改剛才的數(shù)據(jù)。

        (2) 幻讀是讀取了其他事務(wù)新增的數(shù)據(jù),針對(duì)insert和delete操作

        解決:使用表級(jí)鎖,鎖定整張表,事務(wù)A多次讀取數(shù)據(jù)總量之后才釋放該鎖,這個(gè)時(shí)候才允許其他事務(wù)新增數(shù)據(jù)。

        ?

        這時(shí)候再理解事務(wù)隔離級(jí)別就簡(jiǎn)單多了呢。

        ?

        數(shù)據(jù)庫(kù)事務(wù)的隔離級(jí)別

        SQL 標(biāo)準(zhǔn)定義的四種隔離級(jí)別被 ANSI(美國(guó)國(guó)家標(biāo)準(zhǔn)學(xué)會(huì))和 ISO/IEC(國(guó)際標(biāo)準(zhǔn))采用,每種級(jí)別對(duì)事務(wù)的處理能力會(huì)有不同程度的影響。事務(wù)是一系列的動(dòng)作,它們綜合在一起才是一個(gè)完整的工作單元,這些動(dòng)作必須全部完成,如果有一個(gè)失敗的話,那么事務(wù)就會(huì)回滾到最開(kāi)始的狀態(tài),仿佛什么都沒(méi)發(fā)生過(guò)一樣。

        數(shù)據(jù)庫(kù)事務(wù)的隔離級(jí)別有4個(gè),由低到高依次為Read uncommitted 、Read committed 、Repeatable read 、Serializable ,這四個(gè)級(jí)別可以逐個(gè)解決臟讀 、不可重復(fù)讀 、幻讀 這幾類(lèi)問(wèn)題。

        DEFAULT

        默認(rèn)值,表示使用底層數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別。大部分?jǐn)?shù)據(jù)庫(kù)為READ_COMMITTED(MySql默認(rèn)REPEATABLE_READ)

        READ UNCOMMITTED(讀未提交)

        該隔離級(jí)別表示一個(gè)事務(wù)可以讀取另一個(gè)事務(wù)修改但還沒(méi)有提交的數(shù)據(jù)。該級(jí)別不能防止臟讀和不可重復(fù)讀,因此很少使用該隔離級(jí)別。

        READ_COMMITTED (讀提交)

        該隔離級(jí)別表示一個(gè)事務(wù)只能讀取另一個(gè)事務(wù)已經(jīng)提交的數(shù)據(jù)。該級(jí)別可以防止臟讀,這也是大多數(shù)情況下的推薦值。

        REPEATABLE_READ (可重復(fù)讀)

        該隔離級(jí)別表示一個(gè)事務(wù)在整個(gè)過(guò)程中可以多次重復(fù)執(zhí)行某個(gè)查詢,并且每次返回的記錄都相同。即使在多次查詢之間有新增的數(shù)據(jù)滿足該查詢,這些新增的記錄也會(huì)被忽略。該級(jí)別可以防止臟讀和不可重復(fù)讀。

        SERIALIZABLE (串行化)

        所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說(shuō),該級(jí)別可以防止臟讀、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能。通常情況下也不會(huì)用到該級(jí)別。在該隔離級(jí)別下事務(wù)都是串行順序執(zhí)行的,MySQL 數(shù)據(jù)庫(kù)的 InnoDB 引擎會(huì)給讀操作隱式加一把讀共享鎖,從而避免了臟讀、不可重讀復(fù)讀和幻讀問(wèn)題。

        MVCC(多版本并發(fā)控制)

        mysql中,默認(rèn)的事務(wù)隔離級(jí)別是可重復(fù)讀(repeatable-read),為了解決不可重復(fù)讀,innodb采用了MVCC(多版本并發(fā)控制)來(lái)解決這一問(wèn)題。MVCC是利用在每條數(shù)據(jù)后面加了隱藏的兩列(創(chuàng)建版本號(hào)和刪除版本號(hào)),每個(gè)事務(wù)在開(kāi)始的時(shí)候都會(huì)有一個(gè)遞增的版本號(hào),用來(lái)和查詢到的每行記錄的版本號(hào)進(jìn)行比較。?MYSQL MVCC

        Spring事務(wù)傳播行為

        先來(lái)介紹下Spring事務(wù)傳播行為的使用方法:

        @Transactional(propagation=Propagation.REQUIRED)
        public?void?test()?{
        ????????//todo?something
        }
        ?

        注解@Transactional 通過(guò)使用 propagation 屬性設(shè)置,例如:@Transactional(propagation = Propagation.REQUIRED)

        ?

        它的propagation屬性取值有以下幾種:

        public?enum?Propagation?{

        ????REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

        ????SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

        ????MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

        ????REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

        ????NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

        ????NEVER(TransactionDefinition.PROPAGATION_NEVER),

        ????NESTED(TransactionDefinition.PROPAGATION_NESTED);

        }

        事務(wù)傳播行為:

        • REQUIRED :如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。
        • SUPPORTS :如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
        • MANDATORY :如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù),則拋出異常。
        • REQUIRES_NEW :創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
        • NOT_SUPPORTED :以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
        • NEVER :以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。
        • NESTED :如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來(lái)運(yùn)行;如果當(dāng)前沒(méi)有事務(wù),則該取值等價(jià)于 REQUIRED

        Spring 事務(wù)的兩種實(shí)現(xiàn)

        Spring 支持“編程式事務(wù)”管理和“聲明式事務(wù)”管理兩種方式:

        1編程式事務(wù):編程式事務(wù)使用 TransactionTemplate 或者直接使用底層的 PlatformTransactionManager 實(shí)現(xiàn)事務(wù)。對(duì)于編程式事務(wù) Spring 比較推薦使用 TransactionTemplate 來(lái)對(duì)事務(wù)進(jìn)行管理。

        2聲明式事務(wù):聲明式事務(wù)是建立在 AOP 之上的。其本質(zhì)是對(duì)方法前后進(jìn)行攔截,然后在目標(biāo)方法開(kāi)始之前創(chuàng)建或者加入一個(gè)事務(wù),在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況“提交”或者“回滾”事務(wù)。

        兩種事務(wù)管理間的區(qū)別

        • 編程式事務(wù)允許用戶在代碼中精確定義事務(wù)的邊界。
        • 聲明式事務(wù)有助于用戶將操作與事務(wù)規(guī)則進(jìn)行解耦,它是基于 AOP 交由 Spring 容器實(shí)現(xiàn),是開(kāi)發(fā)人員只重點(diǎn)關(guān)注業(yè)務(wù)邏輯實(shí)現(xiàn)。
        • 編程式事務(wù)侵入到了業(yè)務(wù)代碼里面,但是提供了更加纖細(xì)的事務(wù)管理。而聲明式事務(wù)基于 AOP,所以既能起到事務(wù)作用,又可以不影響業(yè)務(wù)代碼的具體實(shí)現(xiàn)。一般而言比較推薦使用聲明式事務(wù),尤其是使用 @Transactional 注解,它能很好地幫助開(kāi)發(fā)者實(shí)現(xiàn)事務(wù)的同時(shí),也減少代碼開(kāi)發(fā)量,且使代碼看起來(lái)更加清爽整潔。

        Spring 編程式事務(wù)

        一般來(lái)說(shuō)編程式事務(wù)有兩種方法可以實(shí)現(xiàn):模板事務(wù)的方式(TransactionTemplate)平臺(tái)事務(wù)管理器方式(PlatformTransactionManager)

        • 模板事務(wù)的方式(TransactionTemplate):主要是使用 TransactionTemplate 類(lèi)實(shí)現(xiàn)事務(wù),這也是 Spring 官方比較推薦的一種編程式使用方式;

        例:

        • ① 獲取模板對(duì)象 TransactionTemplate;
        • ② 選擇事務(wù)結(jié)果類(lèi)型;
        • ③ 業(yè)務(wù)數(shù)據(jù)操作處理;
        • ④ 業(yè)務(wù)執(zhí)行完成事務(wù)提交或者發(fā)生異常進(jìn)行回滾;

        其中 TransactionTemplate 的 execute 能接受兩種類(lèi)型參數(shù)執(zhí)行事務(wù),分別為:

        ?TransactionCallback():?執(zhí)行事務(wù)且可以返回一個(gè)值。
        ?TransactionCallbackWithoutResult():?執(zhí)行事務(wù)沒(méi)有返回值。

        下面是使用 TransactionTemplate 的實(shí)例:

        @Service
        public?class?TransactionExample?{
        ??/**?1、獲取?TransactionTemplate?對(duì)象?**/
        ??@Autowired
        ??private?TransactionTemplate?transactionTemplate;
        ??
        ??public?void?addUser()?{
        ??????//?2、使用?TransactionCallback?或者?TransactionCallbackWithoutResult?執(zhí)行事務(wù)
        ??????transactionTemplate.execute(new?TransactionCallbackWithoutResult()?{
        ??????????@Override
        ??????????public?void?doInTransactionWithoutResult(TransactionStatus?transactionStatus)?{
        ??????????????try?{
        ??????????????????//?3、執(zhí)行業(yè)務(wù)代碼(這里進(jìn)行模擬,執(zhí)行多個(gè)數(shù)據(jù)庫(kù)操作方法)
        ??????????????????userMapper.delete(1);
        ??????????????????userMapper.delete(2);
        ??????????????}?catch?(Exception?e)?{
        ??????????????????//?4、發(fā)生異常,進(jìn)行回滾
        ??????????????????transactionStatus.setRollbackOnly();
        ??????????????}
        ??????????}
        ??????});
        ??}
        ??
        }

        • 平臺(tái)事務(wù)管理器方式(PlatformTransactionManager):這里使用最基本的事務(wù)管理局對(duì)事務(wù)進(jìn)行管理,借助 Spring 事務(wù)的 PlatformTransactionManager 及 TransactionDefinition 和 TransactionStatus 三個(gè)核心類(lèi)對(duì)事務(wù)進(jìn)行操作。

        使用事務(wù)管理器方式實(shí)現(xiàn)事務(wù)步驟:

        • ① 獲取事務(wù)管理器 PlatformTransactionManager;
        • ② 獲取事務(wù)屬性定義對(duì)象 TransactionDefinition;
        • ③ 獲取事務(wù)狀態(tài)對(duì)象 TransactionStatus;
        • ④ 業(yè)務(wù)數(shù)據(jù)操作處理;
        • ⑤ 進(jìn)行事務(wù)提交 commit 操作或者發(fā)生異常進(jìn)行事務(wù)回滾 rollback 操作;
        @Service
        public?class?TransactionExample?{
        ????
        ????/**?1、獲取?PlatformTransactionManager?對(duì)象?**/
        ????@Autowired
        ????private?PlatformTransactionManager?platformTransactionManager;

        ????public?void?addUser()?{
        ????????//?2、獲取默認(rèn)事務(wù)定義
        ????????DefaultTransactionDefinition?def?=?new?DefaultTransactionDefinition();
        ????????//?設(shè)置事務(wù)傳播行為
        ????????def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        ????????//?3、根據(jù)事務(wù)定義對(duì)象設(shè)置的屬性,獲取事務(wù)狀態(tài)
        ????????TransactionStatus?status?=?platformTransactionManager.getTransaction(def);
        ????????try?{
        ????????????//?4、執(zhí)行業(yè)務(wù)代碼(這里進(jìn)行模擬,執(zhí)行多個(gè)數(shù)據(jù)庫(kù)操作方法)
        ????????????userMapper.delete(1);
        ????????????userMapper.delete(2);
        ????????????//?5、事務(wù)進(jìn)行提交
        ????????????platformTransactionManager.commit(status);
        ????????}?catch(Exception?e){
        ????????????//?5、事務(wù)進(jìn)行回滾
        ????????????platformTransactionManager.rollback(status);
        ????????}
        ????}
        ????
        }

        Spring 聲明式事務(wù)

        聲明式事務(wù)(declarative transaction management)顧名思義就是使用聲明的方式來(lái)處理事務(wù)。該方式是基于 Spring AOP 實(shí)現(xiàn)的,將具體業(yè)務(wù)邏輯和事務(wù)處理解耦,其本質(zhì)是在執(zhí)行方法前后進(jìn)行攔截,在方法開(kāi)始之前創(chuàng)建或者加入一個(gè)事務(wù),在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)。

        常用的聲明式事務(wù)使用方法

        常用的聲明式事務(wù)使用方法有

        • 1 XML
        • 2 @Transactional 注解

        兩種方法,由于近幾年 SpringBoot 的流行,提供很方便的自動(dòng)化配置,致使 XML 方式已經(jīng)逐漸淘汰,比較推薦使用注解的方式

        @Transactional 的作用范圍

        注解 @Transactional 不僅僅可以添加在方法上面,還可以添加到類(lèi)級(jí)別上,當(dāng)注解放在類(lèi)級(jí)別時(shí),表示所有該類(lèi)的公共方法都配置相同的事務(wù)屬性信息。如果類(lèi)級(jí)別配置了 @transactional,方法級(jí)別也配置了 @transactional,應(yīng)用程序會(huì)以方法級(jí)別的事務(wù)屬性信息來(lái)管理事務(wù),換言之,方法級(jí)別的事務(wù)屬性信息會(huì)覆蓋類(lèi)級(jí)別的相關(guān)配置。

        @Transactional 注解中可配置參數(shù)
        • value:事務(wù)管理器,此配置項(xiàng)是設(shè)置 Spring 容器中的 Bean 名稱,這個(gè) Bean 需要實(shí)現(xiàn)接口 PlatformTransactionManager。
        • transactionManager:事務(wù)管理器,該參數(shù)和 value 配置保持一致,是同一個(gè)東西。
        • isolation:事務(wù)隔離級(jí)別,默認(rèn)為 Isolation.DEFAULT 級(jí)別
        • propagation:事務(wù)傳播行為,默認(rèn)為 Propagation.REQUIRED
        • timeout:事務(wù)超時(shí)時(shí)間,單位為秒,默認(rèn)值為-1,當(dāng)事務(wù)超時(shí)時(shí)會(huì)拋出異常,進(jìn)行回滾操作。
        • readOnly:是否開(kāi)啟只讀事務(wù),是否開(kāi)啟只讀事務(wù),默認(rèn) false
        • rollbackForClassName:回滾事務(wù)的異常類(lèi)名定義,同 rollbackFor,只是用類(lèi)名定義。
        • noRollbackForClassName:指定發(fā)生哪些異常名不回滾事務(wù),參數(shù)為類(lèi)數(shù)組,同 noRollbackFor,只是使用類(lèi)的名稱定義。
        • rollbackFor:回滾事務(wù)異常類(lèi)定義,當(dāng)方法中出異常,且異常類(lèi)和該參數(shù)指定的類(lèi)相同時(shí),進(jìn)行回滾操作,否則提交事務(wù)。
        • noRollbackFor:指定發(fā)生哪些異常不回滾事務(wù),當(dāng)方法中出異常,且異常類(lèi)和該參數(shù)指定的類(lèi)相同時(shí),不回滾而是將繼續(xù)提交事務(wù)。
        示例
        @Transactional(propagation=Propagation.REQUIRED)
        public?void?test()?{
        ????????//todo?something
        }

        注意: 一般而言,不推薦將 @Transaction 配置到類(lèi)上,因?yàn)檫@樣很可能使后來(lái)的維護(hù)人員必須強(qiáng)制使用事務(wù)。

        使用事務(wù)時(shí)需要注意的點(diǎn)

        • 1、遇到異常檢測(cè)不回滾,原因:默認(rèn)RuntimeException級(jí)別才回滾,如果是Eexception級(jí)別的異常需要手動(dòng)添加
        @Transactional(rollbackFor=Exception.class)
        • 2、捕捉異常后事物不生效,原因:捕捉處理了異常導(dǎo)致框架無(wú)法感知異常,自然就無(wú)法回滾了。建議:若非實(shí)際業(yè)務(wù)要求,則在業(yè)務(wù)層統(tǒng)一拋出異常,然后在控制層統(tǒng)一處理
        @Transactional(rollbackFor=Exception.class)
        public?void?test()?
        {
        ????try?{
        ?????????//業(yè)務(wù)代碼
        ????}?catch?(Exception?e)?{
        ????????//?TODO:?handle?exception
        ????}
        ???//主動(dòng)捕捉異常導(dǎo)致框架無(wú)法捕獲,從而導(dǎo)致事物失效
        }

        總結(jié)

        本章主要講了 事務(wù)基本概念A(yù)CID是什么 ,臟讀、不可重復(fù)讀、幻讀 等等術(shù)語(yǔ)的介紹及例子 數(shù)據(jù)庫(kù)事務(wù)的隔離級(jí)別(4種), Spring事務(wù)傳播行為(7種),事務(wù)的實(shí)現(xiàn)實(shí)例和使用事務(wù)時(shí)需要注意的地方 ?通過(guò)這篇文章,小伙伴們應(yīng)該已經(jīng)對(duì)事務(wù)有了更深的了解吧 ,最后 歡迎關(guān)注我的公眾號(hào):JAVA寶典 或者加我的微信 我們一起探討和學(xué)習(xí).


        瀏覽 130
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

          <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本高清无码在线播放 | 婷婷丁香五月天久久 | 搜黄色一级操逼的 | 亚洲另类色图 | 女女百合舌伸湿润腿间电影 | 蜜桃91 | 欧美一级婬片免费视频华泰老添妇 | 狠狠亲狠狠操 | 久久足交 | 97色色五月天 |