设为首页 收藏本站
查看: 701|回复: 0

[经验分享] PHP跨数据库事务处理

[复制链接]

尚未签到

发表于 2017-4-3 06:11:21 | 显示全部楼层 |阅读模式
一次面试时,被一个CTO鄙视了,他问我PHP有什么做不了的。 我答:只要是Web程序,大部分都没啥问题。 他说:分布式事务,PHP无能为力。 我无言以对(因为我不懂a)
从此,我就经常会想起这个问题,分布式事务实现真的有语言限制吗? 为此我小小地分析了一下跨数据库事务的方方面面。
Mysql完成一个完整xa事务的典型过程。

XA START 'xatest';
INSERT INTO user VALUES(1,'Colin');
INSERT INTO user VALUES(2,'Colin');
XA END 'xatest';
XA PREPARE 'xatest';
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此时认为第二个事务是失败的,如何处理一致性?

function xa_transaction() {
// 假设有两个数据库$db1,$db2
$dbs = {$db1, $db2};
/** 1pc:          忽略 */
/** 2pc - prepare 忽略 */
/** 2pc - committ */
// 首先得记录那些失败的分支事务
$errs = array();
foreach($dbs AS $db) {
//记录失败的db
if(!$db->commit()) {
$errs[] = $db;
} else {
tm_log('committed') // 事务管理器日志记录committed.
}
}
// 反复执行那些失败的事务,直到成功(不回滚成功的分支事务,而是提交失败的分支事务)
foreach($errs AS $db) {
$prepared_tranaction = $db->recover();
if(prepared_tranaction is null) { // 针对问题2,更新事务管理器日志记录为committed.
tm_log('committed') // 事务管理器日志记录committed.
} else {                 // 针对问题1,重新提交
$db->commit();
}
}
}


有必要说明的是这里的关键代码:$db->recover();
其对应着mysql的sql命令xa recover, 该SQL可以查询处当前处于prepared状态还没有committ的事务, 从而可以判定是否要重新提交该分支事务还是简单记录tm端log状态
问题3: 同样假设有两个分支事务,第一个提交成功了,但当刚准备执行第二个事务时,客户端垮掉了。如何保证一致性?
此时,是一个重要的考验TM的地方,它必须有个机制保证客户端重启时,能够重新构造这个全局事务,正确判定其中哪个分支事务没有成功。保证这个机制的实现就是LOG,这个Log在TM端保存,在全局事务的每个关键步骤,TM都应该记录分支事务执行状态,对于该情况导致的问题,当客户端恢复的时候,它分析Log找出失败的事务重新执行其面的提到的xa_transaction().

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

看英文真的头大,此文一半分析一半猜想,恳请懂行的给出正确指导和纠正。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-359301-1-1.html 上篇帖子: PHP 多参数方法的重构 下篇帖子: PHP文档生成工具
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表