上一篇
想象一下这个场景:你的电商网站正在搞促销,同一件商品瞬间被100个用户抢购,PHP脚本欢快地处理着订单,突然——库存显示还剩10件,但实际已经卖超了!这就是典型的并发写入问题:两个请求同时读取库存为10,各自减1后都写回9,最终库存只减了1次,却卖出了两单。
这种时候,数据库锁机制就是你的救星,今天我们就来聊聊如何用PHP+数据库锁,既保证数据安全,又维持数据一致性。
数据库锁的核心就两点:
常见的翻车现场:
原理:给数据加个版本号,修改时检查版本是否变化
// 读取时获取版本号 $row = $pdo->query("SELECT stock, version FROM products WHERE id=1")->fetch(); // 更新时校验版本 $stmt = $pdo->prepare("UPDATE products SET stock=?, version=version+1 WHERE id=1 AND version=?"); $stmt->execute([$newStock, $row['version']]); if ($stmt->rowCount() == 0) { throw new Exception("数据已被修改,请重试"); }
适用场景:商品详情页的库存显示
原理:操作前先锁住记录,别人只能干等着
$pdo->beginTransaction(); // 锁定记录(FOR UPDATE是关键) $stock = $pdo->query("SELECT stock FROM products WHERE id=1 FOR UPDATE")->fetchColumn(); if ($stock > 0) { $pdo->exec("UPDATE products SET stock=stock-1 WHERE id=1"); $pdo->commit(); } else { $pdo->rollBack(); throw new Exception("库存不足"); }
注意:必须配合事务使用,长时间锁会导致性能问题
原理:用文件系统当锁管理器
$lockFile = fopen('order.lock', 'w'); if (flock($lockFile, LOCK_EX)) { // 排他锁 // 处理核心逻辑 processOrder(); flock($lockFile, LOCK_UN); // 释放锁 } else { throw new Exception("系统繁忙,请稍后重试"); } fclose($lockFile);
适用场景:单服务器环境下的定时任务
原理:利用Redis的原子性实现跨服务锁
$redis = new Redis(); $redis->connect('127.0.0.1', 6379); $lockKey = 'product_1_lock'; $token = uniqid(); // 唯一标识 // 尝试加锁(NX表示不存在才设置,EX是过期时间) if ($redis->set($lockKey, $token, ['NX', 'EX' => 30])) { try { // 业务处理 deductStock(); } finally { // 确保只删除自己的锁 if ($redis->get($lockKey) == $token) { $redis->del($lockKey); } } } else { throw new Exception("操作太频繁,请稍候"); }
优势:适合多台PHP服务器共用一个数据库的场景
死锁预防
性能平衡
锁粒度选择
LOCK TABLES products WRITE
(简单但性能差) SELECT ... FOR UPDATE
(推荐) PHP连接池注意
使用PDO时,记得在事务结束后关闭连接,避免长事务占用锁
Web表单防护
// 生成一次性token $_SESSION['form_token'] = bin2hex(random_bytes(32)); // 提交时校验 if ($_POST['token'] !== ($_SESSION['form_token'] ?? '')) { die("请勿重复提交"); }
后台任务加锁
// 使用MySQL的GET_LOCK() $pdo->exec("SELECT GET_LOCK('cron_job', 10)"); // 等待10秒 // 执行任务... $pdo->exec("SELECT RELEASE_LOCK('cron_job')");
锁监控技巧
-- 查看当前锁情况(MySQL) SHOW OPEN TABLES WHERE In_use > 0; SHOW PROCESSLIST;
数据库锁就像交通信号灯——用好了秩序井然,用不好全城堵车,根据你的业务场景:
没有万能的锁方案,只有最适合当前业务场景的选择,测试时不妨模拟100个并发请求,看看你的锁机制是否真的可靠!
本文由 百里向梦 于2025-08-04发表在【云服务器提供商】,文中图片由(百里向梦)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/534950.html
发表评论