本文目录导读:

在PHP项目中实现数据库事务,主要取决于你使用的数据库扩展或ORM框架,以下是几种常见的实现方式:
使用 PDO (PHP Data Objects)
基本事务处理
try {
// 创建PDO连接
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 开始事务
$pdo->beginTransaction();
// 执行多个数据库操作
$pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
$pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
// 提交事务
$pdo->commit();
echo "事务执行成功!";
} catch (Exception $e) {
// 回滚事务
$pdo->rollBack();
echo "事务执行失败:" . $e->getMessage();
}
使用预处理语句的事务
try {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
// 预处理语句
$stmt1 = $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt2 = $pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt1->execute([100, 1]);
$stmt2->execute([100, 2]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
echo "错误:" . $e->getMessage();
}
使用 MySQLi (MySQL Improved)
面向对象方式
// 创建连接
$mysqli = new mysqli('localhost', 'username', 'password', 'test');
// 检查连接
if ($mysqli->connect_error) {
die("连接失败: " . $mysqli->connect_error);
}
// 开始事务
$mysqli->begin_transaction();
try {
// 执行操作
$mysqli->query("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
$mysqli->query("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
// 提交事务
$mysqli->commit();
echo "事务执行成功";
} catch (Exception $e) {
// 回滚事务
$mysqli->rollback();
echo "事务执行失败:" . $e->getMessage();
}
$mysqli->close();
过程化方式
$link = mysqli_connect('localhost', 'username', 'password', 'test');
if (!$link) {
die('连接失败: ' . mysqli_connect_error());
}
// 关闭自动提交
mysqli_autocommit($link, false);
$success = true;
if (!mysqli_query($link, "UPDATE accounts SET balance = balance - 100 WHERE id = 1")) {
$success = false;
}
if (!mysqli_query($link, "UPDATE accounts SET balance = balance + 100 WHERE id = 2")) {
$success = false;
}
if ($success) {
mysqli_commit($link);
echo "事务执行成功";
} else {
mysqli_rollback($link);
echo "事务执行失败";
}
mysqli_close($link);
使用 Laravel 框架
Eloquent ORM 事务
use Illuminate\Support\Facades\DB;
use App\Models\Account;
// 方法1:使用闭包
DB::transaction(function () {
Account::where('id', 1)->decrement('balance', 100);
Account::where('id', 2)->increment('balance', 100);
});
// 方法2:手动控制
try {
DB::beginTransaction();
Account::where('id', 1)->decrement('balance', 100);
Account::where('id', 2)->increment('balance', 100);
DB::commit();
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
事务锁处理
DB::transaction(function () {
// 悲观锁 (行锁)
$account1 = Account::where('id', 1)->lockForUpdate()->first();
$account2 = Account::where('id', 2)->lockForUpdate()->first();
$account1->balance -= 100;
$account2->balance += 100;
$account1->save();
$account2->save();
});
使用 ThinkPHP 框架
use think\facade\Db;
// 方法1:自动事务
Db::transaction(function () {
Db::table('accounts')->where('id', 1)->dec('balance', 100);
Db::table('accounts')->where('id', 2)->inc('balance', 100);
});
// 方法2:手动事务
try {
Db::startTrans();
Db::table('accounts')->where('id', 1)->dec('balance', 100);
Db::table('accounts')->where('id', 2)->inc('balance', 100);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
throw $e;
}
事务最佳实践
检查受影响行数
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ? AND balance >= ?");
$stmt->execute([100, 1, 100]);
if ($stmt->rowCount() === 0) {
throw new Exception("账户余额不足");
}
$stmt = $pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt->execute([100, 2]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
echo "错误:" . $e->getMessage();
}
嵌套事务处理
class TransactionManager {
private $pdo;
private $transactionLevel = 0;
public function beginTransaction() {
if ($this->transactionLevel === 0) {
$this->pdo->beginTransaction();
} else {
$this->pdo->exec("SAVEPOINT trans{$this->transactionLevel}");
}
$this->transactionLevel++;
}
public function commit() {
$this->transactionLevel--;
if ($this->transactionLevel === 0) {
$this->pdo->commit();
}
}
public function rollback() {
$this->transactionLevel--;
if ($this->transactionLevel === 0) {
$this->pdo->rollBack();
} else {
$this->pdo->exec("ROLLBACK TO SAVEPOINT trans{$this->transactionLevel}");
}
}
}
注意事项
- 事务隔离级别:根据业务需求设置合适的隔离级别
- 表引擎:确保使用支持事务的存储引擎(如 InnoDB)
- 异常处理:始终使用 try-catch 块处理事务
- 资源释放:及时关闭数据库连接
- 性能考虑:事务不宜过大,避免长时间锁定资源
选择哪种方式取决于你的项目框架和具体需求,PDO 和 MySQLi 适用于没有框架的项目,而 Laravel、ThinkPHP 等框架提供了更便捷的事务处理方法。