Yii2.0 操作事务多个数据库

烧麦
  • 212

我现在是这样的,项目有很多的数据库,都是在同一个mysql服务器下的,在main.php里面有db,db2,db3 现在是这样的有个入库操作,A表来自于db2,B表来自于db3,在使用事务的时候是这句:

$transaction = \Yii::$app->get('db2')->beginTransaction(); 

我不清楚到底写get('db2')还是get('db3')还是随便都可以??

回复
阅读 1.7k
2 个回答

mysql单纯的事务是不支持跨库的。真要做的话可以使用XA Transactions

1.确认是否开启XA事务支持

clipboard.png
如上,innodb_support_xa为ON 表示已开启,否则需先开启

SET innodb_support_xa = ON

2.XA事务实现

$xid = uniqid("xa_"); // 必须唯一

//两个库指定同一个事务id,表明这两个库的操作处于同一事务中
\Yii::$app->db2->createCommand("XA START '$xid'")->execute();
\Yii::$app->db3->createCommand("XA START '$xid'")->execute();

try {

    // 如下为具体业务代码
    $affectCount = \Yii::$app->db2->createCommand("UPDATE test SET aa='aa' WHERE id=1")->execute();
    if($affectCount == false) {
        throw new \Exception("db2执行失败");
    }

    $affectCount = \Yii::$app->db3->createCommand("UPDATE test2 SET bb='bb' WHERE id=1")->execute();
    if($affectCount == false) {
        throw new \Exception("db3执行失败");
    }

    //阶段1:db2提交准备就绪
    \Yii::$app->db2->createCommand("XA END '$xid'")->execute();
    \Yii::$app->db2->createCommand("XA PREPARE '$xid'")->execute();
    //阶段1:$db3提交准备就绪
    \Yii::$app->db3->createCommand("XA END '$xid'")->execute();
    \Yii::$app->db3->createCommand("XA PREPARE '$xid'")->execute();

    //阶段2:提交两个库
    \Yii::$app->db3->createCommand("XA COMMIT '$xid'")->execute();
    \Yii::$app->db3->createCommand("XA COMMIT '$xid'")->execute();

} catch(\Exception $e) {

    \Yii::$app->db2->createCommand("XA ROLLBACK '$xid'")->execute();
    \Yii::$app->db3->createCommand("XA ROLLBACK '$xid'")->execute();
    die($e->getMessage());
}

代码实现参考如下文章,供参考,未测试
https://blog.csdn.net/soonfly...

实际上使用事务会大大的影响性能,如非业务足够特别,一定要使用分布式事务强烈不建议使用,甚至单库的事务也谨慎使用。

XA transaction support is limited to the InnoDB storage engine.
XA事务只在InnoDB存储引擎中支持

Prior to MySQL 5.7.7, XA transactions were not compatible with replication at all. This was because an XA transaction that was in PREPARED state would be rolled back on clean server shutdown or client disconnect. Similarly, an XA transaction that was in PREPARED state would still exist in PREPARED state in case the server was shutdown abnormally and then started again, but the contents of the transaction could not be written to the binary log. In both of these situations the XA transaction could not be replicated correctly.
官方文档说明,在mysql 5.5.7版本之前,XA也不能完全保证一致性。

通过异步的手段保证事务的最终一致是比较合理的思路。

mysql应该不支持分布式事物。

宣传栏