我正在设计一个提供优惠券(序列号)的网站。所有优惠券代码都生成并保存在这样的表中,而不是在线生成:
v_id voucher status (used?)
-------------------------------------------------------
1 abcdefgabcdefg1 0
2 abcdefgabcdefg2 0
3 abcdefgabcdefg3 0
4 abcdefgabcdefg4 0
成功付款后,我应该向最终用户显示未使用的(状态:0)凭证,但我不确定如何执行此操作,因为该网站可能具有很高的流量,因此多个人可能会在同一毫秒内访问该网站,例如,我不能只使用:
SELECT * FROM table WHERE status=0 LIMIT 0,1;
然后更新它:
UPDATE table SET status=1 WHERE v_id=....
因为两个人可能同时访问,所以我们为两个人提供 v_id=1 序列号(相同的序列号)。
确保显示唯一序列号的最佳方法是什么?
最佳答案
免责声明
此答案中的代码尚未经过测试。应调整每个列名称和表名称以适合您的代码。发布此答案是为了说明如何处理并发性和唯一性。
问题
确保一张优惠券只能使用一次
解决方案
我们将创建另一个表,并用已使用的优惠券填充该表。
提到的表将有一个 foreign key
至 voucher
表,通过其主键引用特定凭证,它将具有相同的列 unique
。这使得优惠券 100% 安全,不会被多次使用
表结构
CREATE TABLE vouchers_uised (
id int unsigned not null auto_increment,
voucher_id int unsigned not null,
unique(voucher_id),
foreign key (voucher_id) references `vouchers` (`id`) on delete cascade
) ENGINE = InnoDB;
逻辑
使用优惠券时,需输入vouchers_used
table 。这是一个简单的表格,因此您所需要做的就是插入一列。
INSERT INTO vouchers_used SET voucher_id = 1;
成功
如果成功,PHP 会将查询/准备语句的结果解释为 true
失败时
失败将发出信号 SQLSTATE
代码 23000
这是 DUPLICATE KEY
的代码。如果您使用PDO
在异常模式下,捕获异常并检查 $e->getCode() == '23000
;`将允许您检查查询是否因优惠券已被使用而失败
如何列出可用优惠券
有两种方法可以处理可用优惠券。
第一个是尝试 JOIN
包含已用优惠券的表格,并过滤掉 vouchers_used
中不存在的优惠券表
第二个是帮助自己使用您想要使用的标志,is_available
在 vouchers
table 。您可以使用一个更新的小触发器来帮助自己 vouchers
每次向表添加一条记录到 vouchers_used
table 。这样你就不必太担心 PHP 代码中的逻辑
触发代码:
DELIMITER $$
CREATE
TRIGGER `vouchers_used_after_insert` AFTER INSERT
ON `vouchers_used`
FOR EACH ROW BEGIN
UPDATE vouchers SET is_used = 1 WHERE id = NEW.voucher_id;
END$$
DELIMITER ;
显示可用优惠券
要显示前端可用的优惠券,一个简单的查询就足够了:
SELECT * FROM vouchers WHERE is_used = 0;
如果同时使用优惠券,unique
约束将阻止用户做任何有损数据完整性的事情。您的工作是相应地解释来自数据库的消息,并同时指示用户优惠券已被使用。
关于php mysql 提供独特的凭证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41062556/