分散式事務(多表多庫)
阿新 • • 發佈:2019-01-08
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日誌.查詢呼叫或儲存過程問題.