PHP跨数据库事务处理

本文内容是网上转载!!

Mysql完成一个完整xa事务的典型过程。 
Sql代码   收藏代码
  1. XA START 'xatest';  
  2. INSERT INTO user VALUES(1,'Colin');  
  3. INSERT INTO user VALUES(2,'Colin');  
  4. XA END 'xatest';  
  5. XA PREPARE 'xatest';  
  6. XA COMMIT 'xatest';  


要想了解跨数据库事务处理,必须彻底清楚两阶段提交协议(2PC),请参考 http://jroller.com/pyrasun/category/XA 。 

根据2PC,PHP如果想实现跨数据库事务处理,那么他担当的角色相当于事务管理器(TM), PHP实现事务管理器几乎从没人提及。在此抛砖引玉。 

根据2PC,事务过程可细分为3个阶段: 
引用
1pc 
2pc-prepare阶段 
2pc-committ阶段 


1pc,2pc-prepare阶段每个分支事务执行失败应该都不是问题,因为只要在2pc-committ阶段之前,都可以用rollback方法。问题就在于commit阶段,假设第一个分支事务已经执行成功,但是第二个事务执行失败,那么如何保持两个数据库数据一致。事务管理器的作用就是要保证两个数据库的提交都回滚、要么保证数据库的提交都成功。 

主流2pc的做法是设法让失败的事务提交成功,而不是让成功的事务回滚。如果非要让成功的事务回滚,那么只能是数据库库管理员根据服务器Log手动回滚了(或者有个补偿式参考http://www.atomikos.com/Publications/TryCancelConfirm  

下面就php如何实现2pc-commit阶段关键问题探讨 

问题1: 假设有两个分支事务,第一个提交成功了,第二个由于数据库服务器突然宕机导致失败,怎么保证一致性?  

问题2: 同样假设有两个分支事务,第一个提交成功了,实际第二个也提交成功了,只是在返回成功消息给PHP端事务管理器(TM)的时候,网络中断,但是TM此时认为第二个事务是失败的,如何处理一致性?

Java代码   收藏代码
  1. function xa_transaction() {  
  2.   // 假设有两个数据库$db1,$db2  
  3.   $dbs = {$db1, $db2};  
  4.   /** 1pc:          忽略 */  
  5.   /** 2pc - prepare 忽略 */  
  6.   
  7.   /** 2pc - committ */  
  8.   // 首先得记录那些失败的分支事务  
  9.   $errs = array();  
  10.   foreach($dbs AS $db) {  
  11.     //记录失败的db  
  12.     if(!$db->commit()) {   
  13.         $errs[] = $db;  
  14.     } else {  
  15.         tm_log('committed'// 事务管理器日志记录committed.  
  16.     }  
  17.   }  
  18.   
  19.   // 反复执行那些失败的事务,直到成功(不回滚成功的分支事务,而是提交失败的分支事务)  
  20.   foreach($errs AS $db) {  
  21.     $prepared_tranaction = $db->recover();   
  22.   
  23.     if(prepared_tranaction is null) { // 针对问题2,更新事务管理器日志记录为committed.  
  24.       tm_log('committed'// 事务管理器日志记录committed.  
  25.     } else {                 // 针对问题1,重新提交  
  26.         
  27.       $db->commit();  
  28.     }  
  29.   }  
  30. }  


有必要说明的是这里的关键代码: $db->recover(); 
其对应着mysql的sql命令xa recover, 该SQL可以查询处当前处于prepared状态还没有committ的事务, 从而可以判定是否要重新提交该分支事务还是简单记录tm端log状态 

问题3: 同样假设有两个分支事务,第一个提交成功了,但当刚准备执行第二个事务时,客户端垮掉了。如何保证一致性?  

此时,是一个重要的考验TM的地方,它必须有个机制保证客户端重启时,能够重新构造这个全局事务,正确判定其中哪个分支事务没有成功。保证这个机制的实现就是 LOG ,这个Log在TM端保存,在全局事务的每个关键步骤,TM都应该记录分支事务执行状态,对于该情况导致的问题,当客户端恢复的时候,它分析Log找出失败的事务重新执行其面的提到的xa_transaction(). 


以下是一个TM/RM的网络结构,仅供参考。 
 


看英文真的头大,此文一半分析一半猜想,恳请懂行的给出正确指导和纠正。 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值