四、利用PHP进行事务处理
在本例中,我们将重新创建前面的商品交换应用,这一次我们将使用PHP。为了简单起见,我们省略了许多无关的细节,这个页面将显示一个产品,并提示用户向他的购物车添加商品,如下所示:
<strong>ComputerABC</strong><br />
Owner: Jack<br />
Price: $12.99<br />
A book about computer!<br />
<form action="purchase.php" method="post">
<input type="hidden" name="itemid" value="1" />
<br />
<input type="submit" value="Purchase!" />
</form>
</p>
你可想而知,在这个页面中显示的数据可以简单地从participant和trunk表中提取。在浏览器中刷新后,这个页面将变成图1的样子。
图1 典型的产品展览
单击Purchase! 按钮将把用户带至purchase.php脚本。同时,还会传递一个变量,即$_POST['itemid']。通过使用这个变量连同一些假定的检索交易方和商品主键的类方法,我们可以利用PostgreSQL的事务来给数据库添加产品,并对交易双方账户中的现金进行相应的增减处理,如清单2所示。
清单2 借助purchase.php交易商品
session_start();
include "pgsql.class.php";
//使用引用某种用户会话表的虚构类来检索参与方的主键,并将会话id映射到一个特定用户
$participant = new participant();
$buyerid = $participant->getparticipantkey();
//给商品id取一个友好的变量名
$itemid = $_POST['itemid'];
//使用虚构的item类来检索商品的卖家和价格
$item = new item();
$sellerid = $item->getitemowner($itemid);
$price = $item->getprice($itemid);
//实例化pgsql类
$pgsqldb = new pgsql("localhost","company","webuser","secret");
//连接到PostgreSQL数据库
$pgsqldb->connect();
//假设事务操作会完全成功
$transactionsuccess = TRUE;
//启动该事务
$pgsqldb->begintransaction();
//从买方账户扣款
$query = "UPDATE participant SET cash=cash-$price WHERE participantid=$buyerid";
$result = $pgsqldb->query($query);
if (!$result OR $result->affectedrows() != 1)
$transactionsuccess = FALSE;
//向卖家的账户打款
$query = "UPDATE participant SET cash=cash+$price WHERE participantid=$sellerid";
$result = $pgsqldb->query($query);
if (!$result OR $result->affectedrows() != 1)
$transactionsuccess = FALSE;
//更新商品的属主
$query = "UPDATE trunk SET participantid=$buyerid WHERE trunkid=$itemid";
$result = $pgsqldb->query($query);
if (!$result OR $result->affectedrows() != 1)
$transactionsuccess = FALSE;
//如果$transactionstatus为True,则提交该事务
//否则,回滚所做修改
if ($transactionsuccess) {
$pgsqldb->commit();
echo "The swap took place! Congratulations!";
} else {
$pgsqldb->rollback();
echo "There was a problem with the swap! :-(";
}
?>
如您所见,运行事务的每一步骤之后都会对查询的状态和受影响的数据记录进行检查。任何时候,只要发现出现错误,$transactionsuccess就会被设为FALSE,并且在该脚本结束时回滚所有步骤。当然,您可以优化这个脚本,让它以步步为营的方式启动各个查询,使得只有在确定前一个查询已正确执行之后才会再进行下一个查询,当然,这项练习就留给您自己了。
五、使用事务的注意事项
使用事务时,有许多事项需要注意,例如:
1、只有当整个过程都必须全部成功时才有必要使用事务。举例来说,向购物车添加产品是一个关键的过程,但是浏览可用的产品则不是。
2、PostgreSQL允许您回滚数据定义语句,即任何用于创建、修改或者丢弃一个数据库对象的语句,这里所说的数据库对象包括表、索引、触发器、函数、视图,等等。
3、事务不能嵌套。在COMMIT或者ROLLBACK命令之前提交多个START TRANSACTION命令是没有效果的。然而,您却可以使用保存点来取得嵌套事务所提供的功能。
六、结束语
在上一篇文章中,我们介绍了PostgreSQL的事务功能的定义,并讲解如何通过PostgreSQL客户端。读者通过阅读本文,将会学习什么是事务,PostgreSQL是如何实现它们的。在本文中,我们将介绍如何在自己的PHP应用程序中如何使用事务。当为商务过程建模的时候,数据库的事务功能极为有用,因为它能确保信息的完整性,而这些信息则是组织内最有价值的资产之一。当建立数据库驱动的应用程序的时候,谨慎的使用数据库的事务功能将为您带来巨大的好处。