本帖最后由 xanewong111 于 2011-03-23 17:42:44 编辑

解决方案 »

  1.   

    function begin_transaction($cnn) {
        static $flag;
        if(isset($flag)) return ;
        mysql_query("BEGIN", $cnn);
        //这里可以有一些错误处理机制
        $flag = 1;
    }
      

  2.   

    另外还有两种方案
    1. 使用mysqli的事务支持...(需要使用mysqli扩展)
    $mysqli = new Mysqli($host, $username, $password, $db);
    $mysqli->autocommit(false);
    //其他处理
    2. 框架处理方式(借鉴java开源框架spring的事务处理)
    如果请求的处理有统一的入口, 那么在入口处开启事务, 并在对具体业务调用的包装处, 根据异常或错误机制, 进行事务的回滚, 提交的管理.
      

  3.   

    方法很多, 除了楼上的, 在这里我附加一个,  没测试,function a()
    {
        mysql_query("BEGIN");    //开始事务定义
        mysql_query("insert into table1 .....");
        mysql_query("COMMIT"); //执行事务
        define('A',true);
    }function b()
    {
        mysql_query("BEGIN");    //开始事务定义
        mysql_query("update table2 .....");
        mysql_query("COMMIT"); //执行事务
        define('B',true);
    }function c()
    {
        mysql_query("BEGIN");    //开始事务定义
        mysql_query("delete table3 .....");    //调用a和b方法
        if( !defined('A')) a();
        if( !defined('B')) b();    mysql_query("COMMIT"); //执行事务
    }c();
      

  4.   

    你的意思是将begin封装一下,在开始之前进行一个检测?我不知道你的这个代码是否能起到检测的效果。明天我测试一下
      

  5.   


    第一个方法我没看懂,这个和自动提交有关系吗?PS:我不能要求服务器必须有mysqli扩展,暂时否掉
    第二个方法就是最终解决方案,我不知道如何实现spring里的这个东西,类似AOP的东西,求解啊。
      

  6.   

    按道理mysql这个重复begin应该返回一个错误或警告,但是似乎没有。
    除了1/2楼的方法, 
    你可以用 set autocommit=0 来开始事务,
    用 commit; set autocommit=1; 或 rollback; set autocommit=1; 来结束/回滚一个事务这样在a()和b()里可以用 select @@autocommit; 来看是否在事务中间,注意不仅是开始事务的begin前需要判断,更重要的是commit前需要判断,因为重复begin不回出错,提前commit才是出错的直接原因
      

  7.   

    这个不太对啊好像。实际上,执行的c方法,代码就就变成了:function c()
    {
    mysql_query("BEGIN");    //开始事务定义
    mysql_query("delete table3 ....."); //下边的2个事务实际上是a和b方法里面的
    mysql_query("BEGIN");    //开始事务定义
    mysql_query("insert into table1 .....");
    mysql_query("COMMIT"); //执行事务 mysql_query("BEGIN");    //开始事务定义
    mysql_query("update table2 .....");
    mysql_query("COMMIT"); //执行事务
    mysql_query("COMMIT"); //执行事务
    }
    现在问题就出来了,里面有3组事务,我的意思是想中间的2组事务,有个监测功能,监测如果上边已经打开了事务,那么就不重复打开了,否则各个事务都生效,那就乱套了,并且失去了事务的意义了。
      

  8.   

    补充:我的意思是想中间的2组事务,有个监测功能,监测如果上边已经打开了事务,那么就不重复打开并且重复commit了。只有第一个begin和最后一个commit生效
      

  9.   


    mysqli的方案和7楼说的是一个意思, 是设置了数据库的autocommit=false. 最终commit/rollback
    function begin_transaction($cnn) {
        static $flag;
        if(isset($flag)) return ;
        mysql_query("BEGIN", $cnn);
        //这里可以有一些错误处理机制
        $flag = 1;
    }
    1楼我写的这个方法是使用了函数的静态变量来做标记, 对开启事务做一个封装, 这个你可以测试, 是没有问题的...另外, 如果你用面向对象的方式, 同样可以做到这种封装, 不过使用静态成员变量就可以...框架的方式, 你得看你的系统框架能否支持有统一的管理连接的入口
      

  10.   

    开启事务的标记判断没问题,问题是commit的时候如何判断?
    我用的是TP。不知道有没有类似的东西。
      

  11.   

    这个最好去mysql版问一下
    事务应是可xiang套的
      

  12.   


    事务是不可以嵌套的。可以用save point达到类似效果
      

  13.   


    楼主,start的时候可以判断,commit的时候用一样的方法就行了
    另外,事务如果规划好,应该可以避免这样的事务嵌套发生,这样写,如果函数调用关系复杂了,很容易出错,调试也很麻烦