php 实现事务锁
PHP 实现事务锁的方法
在 PHP 中实现事务锁通常涉及数据库层面的锁机制,以下是几种常见的方法:
使用 MySQL 事务与行锁
通过 MySQL 的 SELECT ... FOR UPDATE 语句实现行级锁,确保在事务中锁定特定行:

$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$pdo->beginTransaction();
try {
// 锁定某一行
$stmt = $pdo->prepare("SELECT * FROM orders WHERE id = ? FOR UPDATE");
$stmt->execute([$orderId]);
$order = $stmt->fetch();
// 执行业务逻辑
$update = $pdo->prepare("UPDATE orders SET status = ? WHERE id = ?");
$update->execute(['processed', $orderId]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
使用表锁
如果需要锁定整个表,可以使用 LOCK TABLES 语句:

$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$pdo->exec("LOCK TABLES orders WRITE");
try {
// 执行业务逻辑
$update = $pdo->prepare("UPDATE orders SET status = ? WHERE id = ?");
$update->execute(['processed', $orderId]);
$pdo->exec("UNLOCK TABLES");
} catch (Exception $e) {
$pdo->exec("UNLOCK TABLES");
throw $e;
}
使用 Redis 分布式锁
在分布式环境中,可以使用 Redis 实现分布式锁:
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$lockKey = 'order_lock_' . $orderId;
$lockTimeout = 10; // 锁的超时时间(秒)
// 尝试获取锁
$locked = $redis->set($lockKey, 'locked', ['nx', 'ex' => $lockTimeout]);
if ($locked) {
try {
// 执行业务逻辑
// ...
} finally {
// 释放锁
$redis->del($lockKey);
}
} else {
throw new Exception('Failed to acquire lock');
}
使用文件锁
在单机环境下,可以使用文件锁实现简单的互斥:
$lockFile = '/tmp/order_lock_' . $orderId;
$fp = fopen($lockFile, 'w+');
if (flock($fp, LOCK_EX)) {
try {
// 执行业务逻辑
// ...
} finally {
flock($fp, LOCK_UN);
fclose($fp);
}
} else {
throw new Exception('Failed to acquire file lock');
}
注意事项
- 数据库锁需要在事务中使用,确保锁的生效范围。
- 分布式锁需要处理锁的超时和释放问题,避免死锁。
- 文件锁仅适用于单机环境,不适用于分布式系统。






