zl程序教程

您现在的位置是:首页 >  后端

当前栏目

PHP PDO事务处理

PHP 事务处理 PDO
2023-06-13 09:12:02 时间
前面我们介绍了 MySQL 中的事务处理,其实在 PDO 中也是支持事务的,而且在 PDO 中使用事务很容易。前面我们已经介绍了构建和执行 SQL 语句的方式,当需要使用事务时,只要在执行 SQL 语句前使用 PDO::beginTransaction() 方法来启动事务即可。如果数据库底层驱动不支持事务,则抛出一个 PDOException 异常。事务一旦启动,可以使用 PDO::commit() 方法来提交事务,或者使用 PDO::rollBack() 方法来回滚事务。

PDO::beginTransaction() 方法的作用是启动一个事务;当事务中的所有 SQL 语句全部执行成功后,可以使用 PDO::commit() 方法来结束并提交一个事务;如果事务中某个 SQL 语句执行失败了,那么可以使用 PDO::rollBack() 方法来结束并回滚事务,事务中的所有 SQL 语句都将无效。注意,事务中的 SQL 语句要么全部成功执行,要么根本就不执行。

事务通常是通过把一批要执行的 SQL 语句 积蓄 起来,然后使之同时生效而,这样做的好处就是可以大大地提高这些 SQL 语句的执行的效率。换句话说,事务可以使脚本更快,而且更加健壮。

需要注意的是,并非每种数据库都支持事务,因此当第一次打开连接时,PDO 需要在 自动提交 模式下运行。自动提交模式意味着,如果数据库支持,运行的每个查询都有它自己的隐式事务,如果数据库不支持事务,则没有。

提示:PDO 仅在驱动层检查是否具有事务处理能力。如果某些运行时条件意味着事务不可用,且数据库服务接受请求去启动一个事务,PDO::beginTransaction() 将仍然返回 TRUE 而且没有错误。

当脚本结束或连接即将被关闭时,如果尚有未完成的事务,那么 PDO 将自动回滚这个事务。这种安全措施有可以避免在脚本意外终止时出现数据不一致的情况。也就是说,如果没有显式地提交事务,那么当某个地方出错时,将执行回滚来保证数据安全。

下面通过一个简单示例来演示以下 PDO 中事务的使用。假设有 userA 和 userB 两个银行账户,现在使用 userA 账户向 userB 账号中转账,使用事务来保证 userA 账户中转出一定金额的同时,userB 账户中转入相等的金额。

存放 userA 和 userB 两个账户的数据表的表结构如下所示:

DROP TABLE IF EXISTS `account`;
CREATE TABLE `account`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 用户ID ,
  `name` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT 用户名 ,
  `cash` decimal(9, 2) NOT NULL COMMENT 账户余额 ,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;

INSERT INTO `account` VALUES (1, userA , 100000.00);
INSERT INTO `account` VALUES (2, userB , 90000.00);

具体的实现代码如下所示:


 ?php

 $dsn = mysql:dbname=testdb;host=localhost 

 $user = root 

 $password = root 

 $dbh = new PDO($dsn, $user, $password);

 //使用事务之前,要先关闭自动提交。不关闭的话,出现异常的时候没法回滚。

 //据手册描述,ATTR_AUTOCOMMIT 属性只在 mysql、OCI(oracle)、firebird 三种数据库中可用

 $dbh- setAttribute(PDO::ATTR_AUTOCOMMIT, 0);

 $price = 996;

 try {

 $dbh- beginTransaction();

 //用户A账户扣除指定的金额

 $sqlcmd = UPDATE account SET cash=cash-$price WHERE name= userA 

 $affected_rows = $dbh- exec($sqlcmd);

 if ($affected_rows 0) {

 echo 用户A账户扣除成功 . br 

 } else {

 throw new Exception( 用户A账户扣除失败 

 //用户B账户增加指定的金额

 $affected_rows = $dbh- exec( UPDATE account SET cash=cash+$price WHERE name= userB 

 if ($affected_rows 0) {

 echo 用户B账户增加成功 . br 

 } else {

 throw new Exception( 用户B账户增加失败 

 echo 转账成功 

 //若前面两个步骤都成功,则提交事务

 $dbh- commit();

 }catch (PDOException $e) //若前面两个步骤中出现了异常,则回滚

 echo $e- getMessage();

 $dbh- rollback();

 //对事务的使用结束之后,重新开启自动提交

 $dbh- setAttribute(PDO::ATTR_AUTOCOMMIT, 1);

? 

24060.html

mysqlphp