You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高并发PHP礼品卡站点如何修改MySQL查询避免同卡重复售卖

问题修复方案

你遇到的同卡重复售卖问题根源是无锁SELECT在高并发场景下会被多个请求同时读到同一条未使用的礼品卡记录,后续操作自然会出现冲突。你需要按以下规则调整:

前置要求

将步骤1、2、3的所有操作包裹在同一个数据库事务中执行,事务隔离级别设置为*读已提交(READ COMMITTED)*即可,避免跨事务脏读。

步骤1查询语句修改

适配MySQL 8.0+ / MariaDB 10.6+及以上版本

直接在原查询末尾追加FOR UPDATE SKIP LOCKED,即可给查到的礼品卡加排他锁,同时跳过其他事务已经锁定的记录,完全避免重复读卡问题,性能损耗极低:

SELECT id, reference_number, card_number FROM cards WHERE category_id = 3 AND card_case = 'unused' ORDER BY id ASC LIMIT 1 FOR UPDATE SKIP LOCKED;

适配MySQL 5.x等不支持SKIP LOCKED的旧版本

如果你的数据库版本不支持SKIP LOCKED语法,可以调整执行逻辑,先做原子预占再查询:

  1. 先执行预占更新操作(原子操作无并发问题):
UPDATE cards SET card_case = 'used' WHERE category_id = 3 AND card_case = 'unused' ORDER BY id ASC LIMIT 1;
  1. 再查询当前事务刚预占的卡片信息:
SELECT id, reference_number, card_number FROM cards WHERE category_id = 3 AND card_case = 'used' ORDER BY id DESC LIMIT 1;

兜底优化

为了避免极端场景下的异常,建议在插入订单前增加一次卡状态校验:

SELECT count(*) FROM cards WHERE id = 你拿到的卡ID AND card_case = 'unused';

如果返回结果为0,直接终止流程返回库存不足即可。
另外建议给cards表的(category_id, card_case)字段加联合索引,大幅提升查询、更新的效率,避免高并发下出现锁表问题。

内容的提问来源于stack exchange,提问作者Ahmed Fawky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 00:48:01