PHP MySQL事务
简介:在本教程中,您将学习如何在PHP中处理MySQL事务以确保数据库的数据完整性。
事务是一组相互依赖的SQL语句,需要以全有或全无模式执行。
如果所有SQL语句成功执行,则事务成功。
任何语句失败都会触发系统回滚到原始状态,以避免数据不一致。
交易的经典示例是从一个银行帐户到另一个银行帐户的汇款交易。
它需要三个步骤:
检查已转帐帐户的余额,以查看该金额是否足以进行转帐。
如果金额足够,请从转帐的余额中扣除该金额。
将转帐金额添加到收款帐户的余额中。
如果第二步出错,则第三步不应继续。
另外,如果在第三步中发生错误,则第二步必须逆转。
如果发生故障,两个银行帐户的金额均保持不变,或者如果交易成功完成,则可以正确调整。
PHP中的MySQL事务
当您使用PDO创建与支持事务的数据库的连接时,将设置自动提交模式。
这意味着您发出的每个查询都包装在一个隐式事务中。
请注意,并非MySQL中的所有存储引擎都支持事务,例如MyISAM不支持事务,但是InnoDB支持。
要在PHP中处理MySQL事务,请使用以下步骤:
通过调用PDO对象的beginTransaction()方法来启动事务。
将SQL语句和commit()方法调用放在try块中。
通过调用PDO对象的rollBack()方法在catch块中回滚事务。
PHP MySQL交易示例
我们将创建一个名为accounts的表,以演示两个银行帐户之间的资金转移。
首先,执行以下语句创建accounts表:
CREATE TABLE accounts ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR (50) NOT NULL, amount DECIMAL (19, 4) NOT NULL );
第二,在accounts表中插入两行:
INSERT INTO accounts(name,amount) VALUES('John',25000), ('Mary',95000);
三,查询账户表:
SELECT * FROM accounts;
让我们看一下下面的TransactionDemo类:
<?php /** * PHP MySQL Transaction Demo */ class TransactionDemo { const DB_HOST = 'localhost'; const DB_NAME = 'classicmodels'; const DB_USER = 'root'; const DB_PASSWORD = ''; /** * Open the database connection */ public function __construct() { // open database connection $conStr = sprintf("mysql:host=%s;dbname=%s", self::DB_HOST, self::DB_NAME); try { $this->pdo = new PDO($conStr, self::DB_USER, self::DB_PASSWORD); } catch (PDOException $e) { die($e->getMessage()); } } /** * PDO instance * @var PDO */ private $pdo = null; /** * Transfer money between two accounts * @param int $from * @param int $to * @param float $amount * @return true on success or false on failure. */ public function transfer($from, $to, $amount) { try { $this->pdo->beginTransaction(); // get available amount of the transferer account $sql = 'SELECT amount FROM accounts WHERE id=:from'; $stmt = $this->pdo->prepare($sql); $stmt->execute(array(":from" => $from)); $availableAmount = (int) $stmt->fetchColumn(); $stmt->closeCursor(); if ($availableAmount < $amount) { echo 'Insufficient amount to transfer'; return false; } // deduct from the transferred account $sql_update_from = 'UPDATE accounts SET amount = amount - :amount WHERE id = :from'; $stmt = $this->pdo->prepare($sql_update_from); $stmt->execute(array(":from" => $from, ":amount" => $amount)); $stmt->closeCursor(); // add to the receiving account $sql_update_to = 'UPDATE accounts SET amount = amount + :amount WHERE id = :to'; $stmt = $this->pdo->prepare($sql_update_to); $stmt->execute(array(":to" => $to, ":amount" => $amount)); // commit the transaction $this->pdo->commit(); echo 'The amount has been transferred successfully'; return true; } catch (PDOException $e) { $this->pdo->rollBack(); die($e->getMessage()); } } /** * close the database connection */ public function __destruct() { // close the database connection $this->pdo = null; } } // test the transfer method $obj = new TransactionDemo(); // transfer 30K from from account 1 to 2 $obj->transfer(1, 2, 30000); // transfer 5K from from account 1 to 2 $obj->transfer(1, 2, 5000);
我们使用__construct()方法打开数据库连接,并使用__destruct()方法关闭数据库连接。
在transfer()方法中:
首先,我们查询转帐帐户的金额并将其与转帐金额进行比较,以检查转帐帐户的余额是否足够。
其次,在金额足够的情况下,我们从已转帐帐户中扣除转帐金额,并将其添加到接收帐户中。
第三,我们通过调用commit()方法来提交事务。
如果发生任何错误,我们在catch块中调用rollBack()方法以回滚事务。
让我们测试transfer()方法。
// transfer 30K from from account 1 to 2 $obj->transfer(1, 2, 30000);
我们从John的帐户中将3万转移到了Mary的帐户中。
我们收到以下消息:
Insufficient amount to transfer
再进行一次转移:
// transfer 5K from from account 1 to 2 $obj->transfer(1, 2, 5000);
该脚本返回以下消息:
The amount has been transferred successfully.
我们已成功在两个银行帐户之间转帐。
您可以通过以下链接下载源代码:
下载PHP MySQL事务源代码
在本教程中,我们逐步向您展示了如何在PHP中处理MySQL事务以确保数据完整性。