PHP PDO操作mysql事务

来源:互联网 发布:被掩埋的巨人 知乎 编辑:程序博客网 时间:2024/05/16 10:35

mysql事务是把几个操作绑在一起,使他们同时一起完成或者同时全部不运行。数据更新往往牵涉多个表,使用普通更新,如果中间出现差错(比如,服务器突然停止运行了),则更新后的结果非常难办。如果一点都没更新,可以运行程序,重新来过;但部分更新,就要挨个 人工  去查;如果数据量非常大,再人工去查,不仅耗费人力资源,还特别费时间,而收益非常小

在这里介绍PHP PDO操作MYSQL事务:

1、mysql的默认引擎为MYISAM,不支持事务,因此要修改(这里是修改默认引擎的方法,当然也有其他方法): my.ini文件的最低端:[mysqld]    添加代码:  init_connect='set autocommit=0'
default-storage-engine=InnoDB  

然后重新启动数据库服务器,并在查询出运行 :alter table ac engine=INNODB; (即便默认引擎更改了,但当前数据表的引擎还是MYISAM)

2、准备数据表: 见下面的图片(表项都设为 int 类型):

3、PHP文件:

<?php
header("Content-type:text/html;charset=utf-8");
//设置打印输出的格式(text/html,html格式;text/xml,XML格式)及编码方式
$options=array(PDO::MYSQL_ATTR_INIT_COMMAND=>"SET NAMES 'UTF8'");
//防止从数据库里输出中文乱码
try{
    $pdo=new pdo("mysql:host=localhost;dbname=ydc-1","root","",$options);
    $pdo->setAttribute(PDO::ATTR_ERRMODE,  PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
        echo "数据库连接失败:".$e->getMessage();
        exit;
}

    $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0);
    //是否自动提交(0,等待commit命令提交;1,当场就提交),为事务做准备;
try{
        
        $pdo->beginTransaction();  //事务开始     
        $price=(real)500;
        $price2=1000;
        $sql1="select * from ac where us=1";
        $s1=$pdo->query($sql1)->fetch(PDO::FETCH_ASSOC);
        $p1=(real)$s1['ba'];
        /* if($p1<$price)
            throw new PDOException("余额不足,不能购买!");
        */
        $sql="update ac set ba=ba-{$price} where us=1 ";
        $affected_rows=$pdo->exec($sql);
        if(!$affected_rows)
           throw new PDOException("张三转出失败");
        if($p1<$price){
         throw new PDOException("余额不足,不能购买!");
}

//先扣帐,后比较余额是否足够(正常情况下应该先比较余额是否足够,再扣账)

        //$sql="update accounts set balance=balance+{$price} where username=13";
        
        $sql="update ac set ba=ba+{$price} where us1=2";//错误的SQL语句,表项user1不存在
        $affected_rows=$pdo->exec($sql);
        if(!$affected_rows)
                throw new PDOException("向李四转入失败");
        
           echo "交易成功!";
           $pdo->commit();//事务成功,数据提交保存
}catch(PDOException $e)//出现异常,事务停止(后面的停止了,但前面的已经运行了,因此需要回撤)
{
        echo $e->getMessage();
        $pdo->rollback();//事务失败,回滚(回撤失败处之前的事务操作)
}
    $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,1);//事务结束,设置自动提交(之后其他的操作,比如select,需要自动提交)
    $sqlx="select * from ac";
    $info=$pdo->query($sqlx)->fetchAll(PDO::FETCH_ASSOC);
    var_dump($info);



事务的关键在于,无论在任何地方出现异常,所有的操作都要取消(关键要回撤已经运行的操作)。即便是先扣账,再把扣账之前的余额数据拿来对比,不足以支付,也能回撤已经扣掉的帐。因此要使事务成功,除非避开所有异常,否则就是一点都没做。

0 0
原创粉丝点击