Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用MySQL(InnoDB)的交易和订单安全 脚本_Php_Mysql_Innodb - Fatal编程技术网

Php 使用MySQL(InnoDB)的交易和订单安全 脚本

Php 使用MySQL(InnoDB)的交易和订单安全 脚本,php,mysql,innodb,Php,Mysql,Innodb,假设我有一个我要赠送的凭证代码列表,我需要确保如果两个人在同一时间下订单,他们不会得到相同的凭证 桌子 样本数据 示例查询 问题: 我相信订单表中凭证id上的唯一键将防止两个订单具有相同的凭证id,如果插入两次相同的凭证id,则会出现错误/引发异常。这将需要一个while循环在失败时重试。 另一种方法是在选择之前锁定凭单表,并在插入之后释放该锁,以确保不会拾取同一凭单两次 因此,我的问题是: 哪个更快? PHP代码中的while循环 阅读锁定凭单表 还有别的办法吗 编辑 ALTER TA

假设我有一个我要赠送的凭证代码列表,我需要确保如果两个人在同一时间下订单,他们不会得到相同的凭证

桌子 样本数据 示例查询 问题: 我相信
订单
表中
凭证id
上的
唯一键
将防止两个订单具有相同的
凭证id
,如果插入两次相同的凭证id,则会出现错误/引发异常。这将需要一个while循环在失败时重试。 另一种方法是在
选择之前锁定凭单表,并在
插入之后释放该锁,以确保不会拾取同一凭单两次

因此,我的问题是:

  • 哪个更快?
    • PHP代码中的while循环
    • 阅读锁定凭单表
  • 还有别的办法吗
编辑
ALTER TABLE
order
CHANGE
凭证id
凭证id
BIGINT(20)未签名非空

如果
@conceducer\u id
为空(根据需要,因为将没有剩余的凭证),将导致
插入
失败。

您可以使用
启动事务
提交
回滚
来防止SQL中出现争用情况

在您的情况下,我会将您的交易放在由这些代币限定的关键区域。

正确的说法是,最好的方法是在下订单时生成凭证。查看php中sha1()函数的文档。您可以使用唯一信息为凭证添加种子,以防止重复,并将其与唯一ID的自动增量字段一起用于凭证


下订单时,PHP生成一个新凭证,将其保存到数据库中,并将其发送给用户。这样,您不仅可以存储有效的凭证,还可以防止创建重复的凭证。

假设凭证表用完了未使用的凭证,您需要处理这种情况。数据库无法为您解决此问题。InnoDB事务会在
开始
上对数据进行快照,因此我上面的两个选择同时运行将生成相同的
凭证id
,插入失败。我刚刚尝试了这个,第二次插入将等待第一次提交,然后失败。我想唯一的方法是读取并锁定凭单表?不幸的是,这只是一个假设的情况。在“现实世界”中,凭证代码来自外部来源,因此无法由我自己生成。啊,在这种情况下,您需要使用InnoDB(用于交易)设置一个“未使用”凭证表,并在订购时从该表中选择一个凭证,将凭证保存到有效凭证的“活动”表中,然后从另一个表中删除该记录,完成事务。这将为您提供分离,这样您就不必担心在操作第三方供应表时删除“有效”凭证。交易支持将锁定记录,直到它被删除,这样两个人就不会得到相同的凭证。但是,从“未使用”中选择两个将给出相同的id?有没有一种方法可以自动锁定查询选择的行;从
表中选择*;在InnoDB中,它将锁定该表,直到您通过回滚或提交完成事务。因此,您实际上是从InnoDB表中提取记录,然后将其插入另一个表中。如果插入完成,则从InnoDB表中删除该记录并提交。这会阻止其他人从该表中获取相同的记录,因为当允许对该表进行另一次读取时,该记录已消失。当您提交时,它将自动解锁表。此外,如果您想要更多关于transaction和InnoDB在MySQL中如何工作的文档,这是一个很好的资源,提供了一些示例:InnoDB transactions在
BEGIN
上拍摄数据快照,因此,我上面的两个
选择同时运行将产生相同的
凭证id
,插入
失败。由于
凭证id
上的
唯一索引
,因此在不使用事务处理的情况下,无论如何都会发生这种情况。我正在尝试找到将凭证分配给订单的最快方法。到目前为止,我的两个选择是while循环,或者读取锁定表。
CREATE TABLE IF NOT EXISTS `order` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `voucher_id` bigint(20) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `voucher_id` (`voucher_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `order` ADD CONSTRAINT `order_fk` FOREIGN KEY (`voucher_id`) REFERENCES `voucher` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

CREATE TABLE IF NOT EXISTS `voucher` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `code` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `voucher` (`code`) VALUES ('A'), ('B'), ('C');
SELECT @voucher_id := v.id FROM `voucher` v LEFT JOIN `order` o ON o.voucher_id = v.id WHERE o.id IS NULL;
INSERT INTO `order` (`voucher_id`) VALUES (@voucher_id);