事務(wù)處理
事務(wù) (transaction) 是由查詢(xún)和/或更新語(yǔ)句的序列組成。用 begin、start transaction 開(kāi)始事務(wù),rollback 回滾事務(wù),commit 提交事務(wù)。
在開(kāi)始事務(wù)后,可以有若干個(gè) SQL 查詢(xún)或更新語(yǔ)句,每個(gè) SQL 遞交執(zhí)行后,還應(yīng)該有判斷是否正確執(zhí)行的語(yǔ)句,以確定下一步是否回滾,若都被正確執(zhí)行則最后提交事務(wù)。
事務(wù)一旦回滾,數(shù)據(jù)庫(kù)則保持開(kāi)始事務(wù)前狀態(tài)。就好象一個(gè)被編輯的文件不存盤(pán)退出,自然還是保持文件原來(lái)的樣子。
所以,事務(wù)可被視為原子操作,事務(wù)中的 SQL,要么全部執(zhí)行,要不一句都不執(zhí)行。
如果需要一個(gè)事務(wù),則必須用 PDO::beginTransaction() 方法來(lái)啟動(dòng),一旦開(kāi)始了事務(wù),可用 PDO::commit() 或 PDO::rollBack()來(lái)完成,這取決于事務(wù)中的代碼是否運(yùn)行成功。
Tips: MySQL只有 InnoDB 驅(qū)動(dòng)支持事務(wù)處理,默認(rèn) MyIsAM 驅(qū)動(dòng)不支持。
代碼示例
連接數(shù)據(jù)庫(kù):
<?php
try {
// 數(shù)據(jù)庫(kù) PDO 連接
$pdo = new \PDO('mysql:host=localhost;dbname=mydb', 'root', 'root', array(PDO::ATTR_PERSISTENT => true));
// 開(kāi)啟異常處理
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (\PDOException $e) {
echo "數(shù)據(jù)庫(kù)連接失?。?.$e->getMessage();
exit;
}
事務(wù)處理:
在下面例子中,假設(shè)為新員工創(chuàng)建一組條目,分配一個(gè)為 23 的 ID。除了登記資料,還需要記錄工資。
<?php
try {
// 開(kāi)啟事務(wù)處理
$pdo->beginTransaction();
// 執(zhí)行 SQL
$sql1 = $pdo->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
if (!$sql1) {
// 拋出異常
throw new \PDOException("登記資料失敗");
}
$sql2 = $pdo->exec("insert into salarychange (id, amount, changedate) values (23, 50000, NOW())");
if (!$sql2) {
// 拋出異常
throw new \PDOException("記錄工資失敗");
}
// 沒(méi)有錯(cuò)誤則提交事務(wù)
$pdo->commit();
} catch (\PDOException $e) {
// 遇到錯(cuò)誤則回滾事務(wù)
$pdo->rollBack();
echo "Failed: " . $e->getMessage();
}