PHP跨数据库事务处理
2014-06-24 16:36
323 查看
本文内容是网上转载!!
Mysql完成一个完整xa事务的典型过程。
Sql代码
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此时认为第二个事务是失败的,如何处理一致性?
Java代码
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的网络结构,仅供参考。
看英文真的头大,此文一半分析一半猜想,恳请懂行的给出正确指导和纠正。
Mysql完成一个完整xa事务的典型过程。
Sql代码
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此时认为第二个事务是失败的,如何处理一致性?
Java代码
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的网络结构,仅供参考。
看英文真的头大,此文一半分析一半猜想,恳请懂行的给出正确指导和纠正。
相关文章推荐
- PHP跨数据库事务处理
- PHP数据库事务处理
- C#实现数据库事务处理的简单示例代码
- 关于“ORA-02041: 客户数据库未开始一个事务处理”
- 也谈 .NET2.0 事务处理 TransactionScope 的使用:[在访问相同数据库时避免讨厌的分布式事务]
- .NET数据库操作的事务处理
- ORACLE数据库事务处理和故障恢复
- Executing a batch in a transaction--PHP DATA OBJECT(PDO)事务处理中的批量操作
- php插入数据库时的单引号处理
- php 下的事务处理
- 正好整理了一下,自己做了个连接数据库的组件,支持SQLSERVER,ACCESS,ORACLE,FoxPro,MySql,IBM DB2,DBF等数据库,并且支持事务处理
- J2EE -- 数据库事务处理的实现
- 初识jdbc对oracle数据库事务处理(隔离级别)
- ASP.NET里的事务处理(ado.net 数据库应用)
- Java中数据库事务处理的实现
- 分布式跨数据库的事务处理解决方案jta
- ADO和DAO的单数据库的事务处理
- C#实现数据库事务处理示例代码
- ASP.NET里的事务处理(ado.net 数据库应用)
- 在ASP中使用事务处理数据库增/删/改操作