亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

PHP Yii2中事務的使用以及代碼實例

2020-03-22 20:18:15
字體:
來源:轉載
供稿:網友
  • Yii2中事務的使用以及代碼實例

    前言

    一般我們做業務邏輯,都不會僅僅關聯一個數據表,所以,會面臨事務問題。

    數據庫事務(Database Transaction) ,是指作為單個邏輯工作單元執行的一系列操作,要么完全地執行,要么完全地不執行。 事務處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向數據的資源。通過將一組相關操作組合為一個要么全部成功要么全部失敗的單元,可以簡化錯誤恢復并使html' target='_blank'>應用程序更加可靠。一個邏輯工作單元要成為事務,必須滿足所謂的ACID(原子性、一致性、隔離性和持久性)屬性。事務是數據庫運行中的一個邏輯工作單位,由DBMS中的事務管理子系統負責事務的處理。

    準備數據庫引擎為innodb 本文使用的yii版本為2.0.5,只要是2.0以上就沒有問題 運行環境為PHP7.0.0,Mysql5.6

    Yii中的事務

    處理異常
        /**     * 測試事務     */    public function actionTest(){        //創建事務        $tr = Yii::$app->db->beginTransaction();        try {            for($i=1;$i<=3;$i++){                $test = new Areas();                $test->name = 'name'.$i;                $test->sort=1;                if($test->save()){                    echo 'save $i | ';                }            }            $test = new Areas();            $test->name = 'ab'.$i;            $test->sorta=1; //寫入不存在的字段            if(!$test->save()){                'save fail'; //如果沒有寫入就輸出            }            //提交            $tr->commit();        } catch (Exception $e) {            //回滾            $tr->rollBack();            echo  'rollback';        }    }

    運行結果

    save 1 | save 2 | save 3 | rollback

    注意,因為最后的數據沒有插入成功,觸發了事務的回滾,所以數據表沒有新增數據產生。

    觸發事務回滾的原因是代碼出現了異常(Exception)。

    處理數據失敗

    一般來講,我們的運行中的代碼是不會出現這種明顯的異常,這種異常會在開發測試過程中消滅掉。

    而真正造成數據需要回滾的是我們的某個業務出現問題,導致沒有寫入部分的數據。

        /**     * 測試事務     */    public function actionTest(){        //創建事務        $tr = Yii::$app->db->beginTransaction();        try {            for($i=1;$i<=3;$i++){                $test = new Areas();                $test->name = 'name'.$i;                $test->sort=1;                if($test->save()){                    echo 'save $i | ';                }            }            $test = new Areas();            $test->name = null; //數據庫設計name不能為空,人為造成寫入失敗。            $test->sort=1; //寫入不存在的字段            if(!$test->save()){               echo  'save fail'; //如果沒有寫入就輸出            }            //提交            $tr->commit();        } catch (Exception $e) {            //回滾            $tr->rollBack();            echo  'rollback';        }    }

    運行結果如下,數據庫插入了三條數據。

    save 1 | save 2 | save 3 | save fail

    也就是說,如果因為業務邏輯導致某個數據表沒有寫入數據,也沒有出現對應的回滾。

    改進方案如下

        /**     * 測試事務     */    public function actionTest(){        //創建事務        $tr = Yii::$app->db->beginTransaction();        try {            for($i=1;$i<=3;$i++){                $test = new Areas();                $test->name = 'name'.$i;                $test->sort=1;                if($test->save()){                    echo 'save $i | ';                }            }            $test = new Areas();            $test->name = null; //數據庫設計name不能為空,人為造成寫入失敗。            $test->sort=1; //寫入不存在的字段            if(!$test->save()){               throw new yiidbException(); //手動拋出異常,再由下面捕獲。            }            //提交            $tr->commit();        } catch (Exception $e) {            //回滾            $tr->rollBack();            echo  'rollback';        }    }

    運行結果如下,數據庫沒有插入新數據,事務被回滾。

    save 1 | save 2 | save 3 | rollback

    分散的數據處理

    由于實際項目的復雜程度,導致我們的數據庫操作分散在不同的Model中。

    所以,實際項目的代碼不會是上面的樣子。

    模擬需求

    接收參數:

    名字 性別 簽名

    業務處理流程:

    接收參數 由發號器得到用戶的uid,發號器對應數據表增加一位數字 把名字、性別、簽名和上一步的uid寫入用戶信息表 初始化用戶余額表

    回滾觸發時機:

    初始化余額表沒有傳入uid導出沒有寫入數據

    實際代碼

    //Controller    /**     * 測試事務-注冊用戶     */    public function actionReg()    {        //獲取請求        $request = Yii::$app->request;        //設定返回格式        $response = Yii::$app->response;        $response->format = yiiwebResponse::FORMAT_JSON; //返回json        //測試代碼,去掉驗證身份步驟        $name = $request->get('name');        $gender = $request->get('gender');        $sign = $request->get('sign');        //測試代碼,省略參數校驗步驟        $tr = Yii::$app->db->beginTransaction();        try {            //得到uid            $uid = App::getSeNo();            UserProfile::add($uid, $name, $gender, 1, $sign);            $user_balance =    UserBalance::initUserBalance($uid);            $tr->commit(); //提交數據        } catch (Exception $e) {            //回滾            $tr->rollBack();            return $e->getMessage(); //返回自定義異常信息        }        return $user_balance;    }//UserProfile    /**     * 添加用戶信息     * @param $user_id     * @param $nikename     * @param $gender     * @param $user_type     * @param string $intro     * @return UserProfile     * @throws Exception     */    public static function add($user_id, $nikename, $gender,$user_type,$intro='') {        $model = new UserProfile();        $model->gender = $gender;        $model->nikename = $nikename;        $model->user_id = $user_id;        $model->user_type=$user_type;        $model->intro=$intro;        $model->update_time = time();        $insert =$model->insert();        if(!$insert){            throw new Exception('沒有寫入用戶資料');        }        return $model;    }//UserBalance    /**     * 初始化用戶的可提現余額     * @param $user_id     */    public static function initUserBalance($user_id){        $info=self::find()->where(['user_id'=>$user_id])->one();        if(!$info ){            $model=new UserBalance();            $model->user_id = $user_id;            $model->price= '0';            $model->update_time=time();            $insert = $model->insert();            if(!$insert){                throw new Exception('沒有初始化用戶余額');            }            $info=$model;        }        return $info->attributes;    }

    正常的結果如下

    {'id':124,'user_id':1473179883,'price':'0','update_time':1473179883}

    如果把初始化用戶余額部分的user_id沒有傳遞成功,返回的結果如下

    '沒有初始化用戶余額'

    我們可以針對具體情況定位到錯誤所在位置,及時修改。

    事務(Transaction)

    從上面的實際代碼可以看出,創建了事務,只要在范圍內,就算是引入的別的Model也能把異常NG返回,完成回滾操作。

    一般情況下,整個Yii應用使用了同一個數據庫連接,或者說是使用了單例。

    而在yiidbConnection中,又對事務對象進行了緩存:

    class Connection extends Component{    // 保存當前連接的有效Transaction對象    private $_transaction;    // 已經緩存有事務對象,且事務對象有效,則返回該事務對象    // 否則返回null    public function getTransaction()    {        return $this->_transaction && $this->_transaction->getIsActive() ? $this->_transaction : null;    }    // 看看啟用事務時,是如何使用事務對象的    public function beginTransaction($isolationLevel = null)    {        $this->open();        // 緩存的事務對象有效,則使用緩存中的事務對象        // 否則創建一個新的事務對象        if (($transaction = $this->getTransaction()) === null) {            $transaction = $this->_transaction = new Transaction(['db' => $this]);        }        $transaction->begin($isolationLevel);        return $transaction;    }}

    因此,可以認為整個Yii應用,使用了同一個 Transaction 對象,也就是說, Transaction::_level 在整個應用的生命周期中,是有延續性的。 這是實現事務嵌套的關鍵和前提。

    總結

    技術水平的增長來自踩坑,踩坑來自業務增長。

    有時間聊聊職業規劃和發展。 : )

    PHP編程

    鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

  • 發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
    日韩欧美成人精品| 成人激情免费在线| 亚洲成人激情在线观看| 欧美大全免费观看电视剧大泉洋| 国产偷亚洲偷欧美偷精品| 日韩大片免费观看视频播放| 久久好看免费视频| 亚洲电影免费观看高清完整版在线| 欧美成人一区在线| 亚洲成色777777在线观看影院| 欧洲中文字幕国产精品| 欧美黄色片在线观看| 亚洲精品久久久久中文字幕欢迎你| 91网在线免费观看| 韩剧1988在线观看免费完整版| 欧美视频在线免费看| 国产精品精品一区二区三区午夜版| 久久久久久久久久久亚洲| 国产精品揄拍一区二区| 欧美激情18p| 精品无码久久久久久国产| 富二代精品短视频| 日韩精品小视频| 亚洲人成网站免费播放| xvideos亚洲人网站| 在线观看国产精品91| 黄色成人av在线| 色综合久久久888| 欧美日韩免费一区| 国产精品999| 欧美精品一区二区免费| 久久成人人人人精品欧| 中文字幕日韩欧美| 91精品在线观看视频| 国产一区二区三区中文| 久久久精品电影| 日韩亚洲一区二区| 国产成人在线一区二区| 在线观看精品国产视频| 亚洲最大成人网色| 国产精品高潮视频| 精品国产91久久久久久老师| 中文字幕成人精品久久不卡| 亚洲另类欧美自拍| 欧美性猛交xxxxx免费看| 久久久久久久久久久免费精品| 成人在线观看视频网站| 亚洲欧洲国产一区| 国产精品一香蕉国产线看观看| www.99久久热国产日韩欧美.com| 国产亚洲人成网站在线观看| 热久久视久久精品18亚洲精品| 一区二区三区回区在观看免费视频| 色伦专区97中文字幕| 欧美性猛交xxxx黑人| 国产精品com| 欧美性猛交xxxx黑人猛交| 成人精品久久av网站| 国产亚洲精品一区二区| 国内精品视频久久| 在线观看欧美日韩国产| 欧美日韩国产成人| 国产香蕉精品视频一区二区三区| 性色av一区二区三区在线观看| 国产精品久久久久久久久久久久久| 亚洲免费一在线| 日韩欧美亚洲一二三区| 91精品国产自产91精品| 国产手机视频精品| 亚洲加勒比久久88色综合| 成人日韩av在线| 精品久久久久久国产91| 中文字幕日韩av综合精品| 性欧美亚洲xxxx乳在线观看| 亚洲国产精久久久久久| 狠狠久久亚洲欧美专区| 91av在线不卡| 欧美一区二区三区免费观看| 亚洲的天堂在线中文字幕| 91久久中文字幕| 国产精品吊钟奶在线| 亚洲最新视频在线| 成人精品久久久| 日韩小视频在线观看| 国产一区二区三区在线观看网站| 久久久久久com| 国产精品91久久久久久| 国产精品视频久| 欧美小视频在线观看| 国产精品久久久久国产a级| 亚洲精品videossex少妇| 日韩动漫免费观看电视剧高清| 久久免费福利视频| 日本韩国欧美精品大片卡二| 亚洲网站在线看| 久久久国产精品亚洲一区| 日本一区二三区好的精华液| 欧美日韩中文字幕日韩欧美| 国产精品久久电影观看| 国产91精品最新在线播放| 国产精品日日做人人爱| 欧美精品中文字幕一区| 亚洲91精品在线观看| 日韩视频免费看| 亚洲性视频网站| 久久久免费观看| 日韩在线观看你懂的| 色777狠狠综合秋免鲁丝| 亚洲直播在线一区| 久久久精品2019中文字幕神马| 亚洲精品自拍视频| 亚洲sss综合天堂久久| 成人黄色av播放免费| 日韩欧美成人精品| 日韩视频在线免费观看| 国产精品精品视频一区二区三区| 午夜精品一区二区三区在线| 永久555www成人免费| 欧美激情videos| 高清视频欧美一级| 欧美日韩在线观看视频| 麻豆精品精华液| 国产精品高潮呻吟久久av无限| 国产高清视频一区三区| 欧美精品电影免费在线观看| 国产伊人精品在线| 亚洲www视频| 欧美日产国产成人免费图片| 成人欧美一区二区三区黑人| 成人免费看吃奶视频网站| 国产精品成av人在线视午夜片| 色老头一区二区三区| 亚洲第一页中文字幕| 韩国日本不卡在线| 久久视频在线免费观看| 日韩精品在线观看一区二区| 中文字幕精品www乱入免费视频| 中文字幕亚洲欧美一区二区三区| 日本在线观看天堂男亚洲| 国产成人一区二区在线| 久久国产精品久久国产精品| 一本大道亚洲视频| 亚洲欧美制服另类日韩| 国产极品精品在线观看| www国产亚洲精品久久网站| 正在播放国产一区| 午夜精品久久17c| 亚洲国内精品在线| 日韩小视频在线观看| 日韩成人av网址| 九九热r在线视频精品| 亚洲国产精品资源| 在线成人激情视频| 久久人体大胆视频| 成人黄色中文字幕| 日韩久久精品成人| 亚洲视频在线播放| 国产精品极品美女粉嫩高清在线| 欧美放荡办公室videos4k| 欧美激情第6页| 高清在线视频日韩欧美| 亚洲成人久久一区| 狠狠久久五月精品中文字幕| 日韩欧美在线视频观看|