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