分布式事务(多表多库)

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日志.查找调用或存储过程问题.

你可能感兴趣的:(php,mysql)