PHP项目数据库事务如何代码实现

wen PHP项目 28

本文目录导读:

PHP项目数据库事务如何代码实现

  1. 使用 PDO (PHP Data Objects)
  2. 使用 MySQLi (MySQL Improved)
  3. 使用 Laravel 框架
  4. 使用 ThinkPHP 框架
  5. 事务最佳实践

在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}");
        }
    }
}

注意事项

  1. 事务隔离级别:根据业务需求设置合适的隔离级别
  2. 表引擎:确保使用支持事务的存储引擎(如 InnoDB)
  3. 异常处理:始终使用 try-catch 块处理事务
  4. 资源释放:及时关闭数据库连接
  5. 性能考虑:事务不宜过大,避免长时间锁定资源

选择哪种方式取决于你的项目框架和具体需求,PDO 和 MySQLi 适用于没有框架的项目,而 Laravel、ThinkPHP 等框架提供了更便捷的事务处理方法。

抱歉,评论功能暂时关闭!