最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

PHP中實(shí)現(xiàn)MySQL嵌套事務(wù)的兩種解決方案

 更新時(shí)間:2015年02月09日 10:20:06   投稿:junjie  
這篇文章主要介紹了PHP中實(shí)現(xiàn)MySQL嵌套事務(wù)的兩種解決方案,本文分析了doctrine和laravel的實(shí)現(xiàn)方式,并提取出來(lái)分析和總結(jié),需要的朋友可以參考下

一、問(wèn)題起源

在MySQL的官方文檔中有明確的說(shuō)明不支持嵌套事務(wù):

復(fù)制代碼 代碼如下:

Transactions cannot be nested. This is a consequence of the implicit commit performed for any current transaction when you issue a START TRANSACTION statement or one of its synonyms.

但是在我們開(kāi)發(fā)一個(gè)復(fù)雜的系統(tǒng)時(shí)難免會(huì)無(wú)意中在事務(wù)中嵌套了事務(wù),比如A函數(shù)調(diào)用了B函數(shù),A函數(shù)使用了事務(wù),并且是在事務(wù)中調(diào)用了B函數(shù),B函數(shù)也有一個(gè)事務(wù),這樣就出現(xiàn)了事務(wù)嵌套。這時(shí)候其實(shí)A的事務(wù)就意義不大了,為什么呢?上面的文檔中就有提到,簡(jiǎn)單的翻譯過(guò)來(lái)就是:
復(fù)制代碼 代碼如下:

當(dāng)執(zhí)行一個(gè)START TRANSACTION指令時(shí),會(huì)隱式的執(zhí)行一個(gè)commit操作。

所以我們就要在系統(tǒng)架構(gòu)層面來(lái)支持事務(wù)的嵌套。所幸的是在一些成熟的ORM框架中都做了對(duì)嵌套的支持,比如doctrine或者laravel。接下來(lái)我們就一起來(lái)看下這兩個(gè)框架是怎樣來(lái)實(shí)現(xiàn)的。

友情提示,這兩個(gè)框架的函數(shù)和變量的命名都比較的直觀,雖然看起來(lái)很長(zhǎng),但是都是通過(guò)命名就能直接得知這個(gè)函數(shù)或者變量的意思,所以不要一看到那么一大坨就被嚇到了 :)

二、doctrine的解決方案

首先來(lái)看下在doctrine中創(chuàng)建事務(wù)的代碼(干掉了不相關(guān)的代碼):

復(fù)制代碼 代碼如下:

public function beginTransaction()
{
    ++$this->_transactionNestingLevel;
    if ($this->_transactionNestingLevel == 1) {
        $this->_conn->beginTransaction();
    } else if ($this->_nestTransactionsWithSavepoints) {
        $this->createSavepoint($this->_getNestedTransactionSavePointName());
    }
}

這個(gè)函數(shù)的第一行用一個(gè)_transactionNestingLevel來(lái)標(biāo)識(shí)當(dāng)前嵌套的級(jí)別,如果是1,也就是還沒(méi)有嵌套,那就用默認(rèn)的方法執(zhí)行一下START TRANSACTION就ok了,如果大于1,也就是有嵌套的時(shí)候,她會(huì)幫我們創(chuàng)建一個(gè)savepoint,這個(gè)savepoint可以理解為一個(gè)事務(wù)記錄點(diǎn),當(dāng)需要回滾時(shí)可以只回滾到這個(gè)點(diǎn)。

然后看下rollBack函數(shù):

復(fù)制代碼 代碼如下:

public function rollBack()
{
    if ($this->_transactionNestingLevel == 0) {
        throw ConnectionException::noActiveTransaction();
    }

    if ($this->_transactionNestingLevel == 1) {
        $this->_transactionNestingLevel = 0;
        $this->_conn->rollback();
        $this->_isRollbackOnly = false;
    } else if ($this->_nestTransactionsWithSavepoints) {
        $this->rollbackSavepoint($this->_getNestedTransactionSavePointName());
        --$this->_transactionNestingLevel;
    } else {
        $this->_isRollbackOnly = true;
        --$this->_transactionNestingLevel;
    }
}


可以看到處理的方式也很簡(jiǎn)單,如果level是1,直接rollback,否則就回滾到前面的savepoint。

然后我們繼續(xù)看下commit函數(shù):

復(fù)制代碼 代碼如下:

public function commit()
{
    if ($this->_transactionNestingLevel == 0) {
        throw ConnectionException::noActiveTransaction();
    }
    if ($this->_isRollbackOnly) {
        throw ConnectionException::commitFailedRollbackOnly();
    }

    if ($this->_transactionNestingLevel == 1) {
        $this->_conn->commit();
    } else if ($this->_nestTransactionsWithSavepoints) {
        $this->releaseSavepoint($this->_getNestedTransactionSavePointName());
    }

    --$this->_transactionNestingLevel;
}


算了,不費(fèi)口舌解釋這段了吧 :)

三、laravel的解決方案

laravel的處理方式相對(duì)簡(jiǎn)單粗暴一些,我們先來(lái)看下創(chuàng)建事務(wù)的操作:

復(fù)制代碼 代碼如下:

public function beginTransaction()
{
    ++$this->transactions;

    if ($this->transactions == 1)
    {
        $this->pdo->beginTransaction();
    }
}


感覺(jué)如何?so easy吧?先判斷當(dāng)前有幾個(gè)事務(wù),如果是第一個(gè),ok,事務(wù)開(kāi)始,否則就啥都不做,那么為啥是啥都不做呢?繼續(xù)往下看rollBack的操作:
復(fù)制代碼 代碼如下:

public function rollBack()
{
    if ($this->transactions == 1)
    {
        $this->transactions = 0;

        $this->pdo->rollBack();
    }
    else
    {
        --$this->transactions;
    }
}


明白了吧?只有當(dāng)當(dāng)前事務(wù)只有一個(gè)的時(shí)候才會(huì)真正的rollback,否則只是將計(jì)數(shù)做減一操作。這也就是為啥剛才說(shuō)laravel的處理比較簡(jiǎn)單粗暴一些,在嵌套的內(nèi)層里面實(shí)際上是木有真正的事務(wù)的,只有最外層一個(gè)整體的事務(wù),雖然簡(jiǎn)單粗暴,但是也解決了在內(nèi)層新建一個(gè)事務(wù)時(shí)會(huì)造成commit的問(wèn)題。原理就是這個(gè)樣子了,為了保持完整起見(jiàn),把commit的代碼也copy過(guò)來(lái)吧!
復(fù)制代碼 代碼如下:

public function commit()
{
    if ($this->transactions == 1) $this->pdo->commit();

    --$this->transactions;
}

相關(guān)文章

  • 新手必備之MySQL msi版本下載安裝圖文詳細(xì)教程

    新手必備之MySQL msi版本下載安裝圖文詳細(xì)教程

    今天教大家怎么下載安裝MySQL msi版本,文中有非常詳細(xì)的圖文解說(shuō),對(duì)不會(huì)下載安裝mysql的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • Mysql鎖之共享鎖(讀鎖)和排他鎖(寫(xiě)鎖)詳解

    Mysql鎖之共享鎖(讀鎖)和排他鎖(寫(xiě)鎖)詳解

    這篇文章主要介紹了Mysql鎖之共享鎖(讀鎖)和排他鎖(寫(xiě)鎖),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 詳解MySQL8的新特性ROLE

    詳解MySQL8的新特性ROLE

    這篇文章主要介紹了詳解MySQL8的新特性ROLE的相關(guān)資料,幫助大家更好的理解和使用MySQL8,感興趣的朋友可以了解下
    2020-11-11
  • MYSQL大表加索引的實(shí)現(xiàn)

    MYSQL大表加索引的實(shí)現(xiàn)

    本文主要介紹了MYSQL大表加索引的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Mysql實(shí)時(shí)備份實(shí)現(xiàn)方法

    Mysql實(shí)時(shí)備份實(shí)現(xiàn)方法

    這篇文章主要介紹了Mysql實(shí)現(xiàn)實(shí)時(shí)備份,需要的朋友可以參考下
    2016-02-02
  • MYSQL GROUP BY用法詳解

    MYSQL GROUP BY用法詳解

    這篇文章主要為大家詳細(xì)介紹了MYSQL GROUP BY用法,具有一定的實(shí)用性和參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • MySQL?source導(dǎo)入很慢的解決方法

    MySQL?source導(dǎo)入很慢的解決方法

    在mysql導(dǎo)入數(shù)據(jù)量非常大的sql文件的時(shí)候,速度會(huì)非常慢,這篇文章主要給大家介紹了關(guān)于MySQL?source導(dǎo)入很慢的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • MySQL不適合創(chuàng)建索引的11種情況示例分析

    MySQL不適合創(chuàng)建索引的11種情況示例分析

    這篇文章介紹了在MySQL中不適合創(chuàng)建索引的11種情況,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-02-02
  • 在MySQL中修改密碼及訪問(wèn)限制的設(shè)置方法詳解

    在MySQL中修改密碼及訪問(wèn)限制的設(shè)置方法詳解

    MySQL是一個(gè)真正的多用戶、多線程SQL數(shù)據(jù)庫(kù)服務(wù)器。MySQL是以一個(gè)客戶機(jī)/服務(wù)器結(jié)構(gòu)的實(shí)現(xiàn),它由一個(gè)服務(wù)器守護(hù)程序mysqld和很多不同的客戶程序和庫(kù)組成。
    2007-03-03
  • MySQL日志管理和備份與恢復(fù)

    MySQL日志管理和備份與恢復(fù)

    這篇文章主要介紹了MySQL如何實(shí)現(xiàn)日志的管理,備份與恢復(fù),本文有一定的參考價(jià)值,感興趣的小伙伴可以參考閱讀
    2023-04-04

最新評(píng)論

宿松县| 永嘉县| 麦盖提县| 高邑县| 漾濞| 阿勒泰市| 信丰县| 洪江市| 科技| 河池市| 桐梓县| 芮城县| 托克托县| 滕州市| 九寨沟县| 冕宁县| 曲松县| 德兴市| 万盛区| 峨边| 临安市| 当涂县| 静安区| 景德镇市| 三亚市| 白朗县| 中西区| 桂林市| 谢通门县| 荔浦县| 鄂尔多斯市| 陆丰市| 岳池县| 苍溪县| 龙井市| 德昌县| 军事| 汕头市| 南宁市| 沂南县| 庐江县|