【求助】PHP+MySQL分布式事务(XA),不能回滚

Hpyer 发布于 2016/05/11 21:21
阅读 391
收藏 4

<?php
$conn1 = new mysqli("127.0.0.1","root","123456","db1","3306");
$conn2 = new mysqli("127.0.0.1","root","123456","db2","3306");

$grid = uniqid("");

$conn1->query("SET autocommit=0;");
$conn2->query("SET autocommit=0;");
$conn1->query("XA START '$grid'");
$conn2->query("XA START '$grid'");

$mobile = '123456';
$user_id = '111111';
$username = 'test111';

try {

    $return11 = $conn1->query("INSERT INTO user (`user_id`, `username`) VALUES ('$user_id', '$username')");
    if($return11 == false) {
        throw new Exception("conn1 fail 11");
    }

    $return12 = $conn1->query("INSERT INTO user_00 (`user_id`, `username`) VALUES ('$user_id', '$username')");
    if($return12 == false) {
        throw new Exception("conn1 fail 12");
    }

    $return21 = $conn2->query("INSERT INTO user_mobile_map (`mobile`, `user_id`) VALUES ('$mobile', '$user_id')");
    if($return21 == false) {
        throw new Exception("conn1 fail 21");
    }

    $return22 = $conn2->query("INSERT INTO user_mobile_xxx (`mobile`, `user_id`) VALUES ('$mobile', '$user_id')");
    if($return22 == false) {
        throw new Exception("conn2 fail 22");
    }

    $conn1->query("XA END '$grid'");
    $conn2->query("XA END '$grid'");

    $conn1->query("XA PREPARE '$grid'");
    $conn2->query("XA PREPARE '$grid'");

    $conn1->query("XA COMMIT '$grid'");
    $conn2->query("XA COMMIT '$grid'");
} catch (Exception $e) {

    $conn1->query("XA END '$grid'");
    $conn2->query("XA END '$grid'");

    $conn2->query("XA ROLLBACK '$grid'");
    $conn1->query("XA ROLLBACK '$grid'");
    print $e->getMessage();
}
$conn1->query("SET autocommit=1;");
$conn2->query("SET autocommit=1;");

$conn1->close();
$conn2->close();



代码是参考这篇文章写的《http://javalifuqing.blog.163.com/blog/static/8369903520124295232311/》

其中$conn2故意把第二个insert语句写错来测试事务的回滚

测试的结果是:$conn1的两个插入操作回滚了,$conn2第一次插入的数据不能回滚

自己后来发现程序在执行$conn1的第一次插入语句的时候,数据就已经进入数据库了,估计是两个链接的事务没有关联起来,,但是谷歌了很久没找到解决办法(也许是用的关键词不对)

跪求各路大神帮忙看看,要怎么解决,或者有什么好的解决方案。

测试环境:Ubuntu14.04 + php 5.5.9 + MySQL5.5.49

加载中
0
此用户已关机
此用户已关机
饿,水平不行,只想到这样尝试
1.确定db2是否支持事物
2.注释掉db1的代码,只测试db2是否正常
3.没其他想法了
Hpyer
Hpyer
谢谢,自己折腾出来了。。确实如你第一条所说,db2的表类型选错了;你第二条方法也试过了,是正常的。
0
Hpyer
Hpyer

自己折腾出来了。。。主要两个问题

第一,自己挖的坑,建user_mobile_map表的时候没注意,类型选成了myisam(我内心是奔溃的~)。解决:改成innodb

第二,$conn1和$conn2不能是同一个数据库实例。分开两个实例就没问题,但是同一个实例的话,还是不能回滚(个人猜测是事务冲突了,求大神解释一下)

Hpyer
Hpyer
第二个问题中不能用同一个数据库实例的解决办法:$conn1和$conn2使用不同的$grid即可。。感谢Tuesday的提醒
0
Tuesday
Tuesday
$grid 只用了一个相同的? 换成不同的试试. 
Hpyer
Hpyer
还真的是这个问题。。。好多文章里都是用同一个grid的。。谢谢谢谢~
返回顶部
顶部