1. 程式人生 > >分散式事務(多表多庫)

分散式事務(多表多庫)

yii下一個分散式事務處理(多表多庫)

controller

/**
    public function actionReview(){
        $user=Yii::app()->user;
        $userid = @$user->user_id;

        $orderid =  Yii::app()->request->getParam('orderid');
        $wf_id = Yii::app()->request->getParam('wf_id');
        $rebate = Yii::app()->request->getParam('rebate'
); $wf = Workflow::model()->findByPk($wf_id); $orderinfo = DOrdersInfo::getOrderInfoId($orderid); if ($orderinfo){ $orders = Orders::model()->find("order_number='".$orderinfo['order_number']."'"); $rebate_total = floatval($orders['contract_price'
]) * ($rebate/100); } if(Yii::app()->request->getPost('submit')){ $msg = ''; if($orderinfo){ $settle_date = Yii::app()->request->getPost('settle_date'); $settle_date = $settle_date?strtotime($settle_date):time(); $invoice_date
= Yii::app()->request->getPost('invoice_date'); $invoice_date = $invoice_date?strtotime($invoice_date):time(); //訂 $pagam['settle_state']= Yii::app()->request->getPost('settle'); $pagam['settle_date']= $settle_date; $pagam['related_order_number']=$orderinfo['related_order_number']; //工 $pagam['wf_id']= $wf_id; $pagam['ptime']= date('Y-m-d H:i:s'); $res_m = Workflow::updateInfom($pagam); //更新 //夥 $bills_pagam = array( 'money' => Yii::app()->request->getPost('sales_interest'), 'channel' => $orders['channel_id'], 'order_number' => $orders['order_number'] ); $bills = Workflow::createBills($bills_pagam); //事務處理 if ($res_m['status'] == 'success' && $bills['status'] == 'success'){ Wow::commit_m($res_m['XA']); Wow::commit_n($bills['XA']); }else { Workflow::rollback_m($res_m['XA']); Workflow::rollback_n($bills['XA']); } }else{ $this->renderPartial('/public/error',array('msg'=>'該訂不存在')); } $this->renderPartial('/public/success',array('msg'=>'確認成功','goto'=>'/workflow/index?status=0','reload'=>false)); }else{ $this->renderPartial('review',array('orderinfo'=>$orderinfo,'wf_id'=>$wf_id,'rebate'=>$rebate_total)); } }

model

/**
    * @date: 2015-11-5
    * @author: 
    * @desc:
    */
    public static function updateInfom($pagam){
        $XA = uniqid("");
        Yii::app()->db->createCommand("XA START '".$XA."'")->query();
        $_rs = true;
        try {
            //更新
            $order_sql = "update ordrs set sett_state='".$pagam."',sett_date='".$pagam2."';
            $res_order = Yii::app()->db->createCommand($order_sql)->execute();
            //關閉
            $close_sql = "update workw set operator='".$pagam."',status='".$pagam2."';
            $res_close = Yii::app()->db->createCommand($close_sql)->execute();
            //工備
            $workflow_log = new WorkflowLog();
            $workflow_log->wf_id = $wf_id;
            $res_wflog = $workflow_log->insert();
            if (!$res_order && !$res_close && !$res_wflog){
                $_rs = false;
            }
        }catch (Exception $e){
            var_dump($e);
            $_rs = false;
        }
        Yii::app()->db->createCommand("XA END '".$XA."'")->query();
        if ($_rs){
            Yii::app()->db->createCommand("XA PREPARE '".$XA."'")->query();
            return array("status"=>"success","XA"=>$XA);
        }else {
            return array("status"=>"nosuccess","XA"=>$XA);
        }
    }

/**

    public static function createBills($pagam){
        $XA = uniqid("");
        Yii::app()->dbnew->createCommand("XA START '".$XA."'")->query();
        $_rs = true;
        try {
            $sql = "insert into bills(type,money) values(1,$money)";
            $result = Yii::app()->dbnew->createCommand($sql)->execute();
            if (!$result){
                $_rs = false;
            }
        }catch (Exception $e){
            var_dump($e);
            $_rs = false;
        }
        Yii::app()->dbnew->createCommand("XA END '".$XA."'")->query();
        if ($_rs){
            Yii::app()->dbnew->createCommand("XA PREPARE '".$XA."'")->query();
            return array("status"=>"success","XA"=>$XA);
        }else {
            return array("status"=>"nosuccess","XA"=>$XA);
        }
    }

    /**
    * @date: 2015-11-4
    * @author: 
    * @desc: 事務
    */
    public static function commit_m($xa){
        return Yii::app()->db->createCommand("XA COMMIT '".$xa."'")->query();
    }
    /**
    * @date: 2015-11-4
    * @author: 
    * @desc: 回滾
    */
    public static function rollback_m($xa){
        return Yii::app()->db->createCommand("XA ROLLBACK '".$xa."'")->query();
    }
    /**
     * @date: 2015-11-4
     * @author: 
     * @desc: 事務
     */
    public static function commit_n($xa){
        return Yii::app()->dbnew->createCommand("XA COMMIT '".$xa."'")->query();
    }
    /**
     * @date: 2015-11-4
     * @author: 
     * @desc: 回滾
     */
    public static function rollback_n($xa){
        return Yii::app()->dbnew->createCommand("XA ROLLBACK '".$xa."'")->query();
    }

可能出現的問題

問題1.
如何生成事務的唯一xid.
解決方法:
參照mysql xid的手冊,寫一個生成方法!

問題2.

在window上採用pdo_mysql只能執行一次儲存過程,所以更不用說分佈事務了.
解決方法:
更換平臺在Linux上進行測試,就沒問題呢!

問題3:
XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state

分析
1.可能是有隱含事務在前面執行.
2 可能有不支援SQL

解決方法:
1)避免不能在事務裡使用的SQL
2)檢查涉及表結構不是INNODB
3)檢查的儲存過程有錯誤
4)避免接口裡資料API是否已經有事務語句執行!

問題4:
失敗了,事務不XA ROLLBACK
分析:
程式呼叫或儲存過程編寫有問題.

問題5:
事務中單庫(多表)只能對應唯一的xid

解決:
1 開啟mysql的generalog 迸行察看sql日誌.查詢呼叫或儲存過程問題.