更新/分配外键到预先存在的表行并且不覆盖它[mysql]
我有一个名为 Promotion_codes 的表。
CREATE TABLE promotion_codes (
id int(10) UNSIGNED NOT NULL auto_increment,
created_at datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
code varchar(255) NOT NULL,
order_id int(10) UNSIGNED NULL DEFAULT NULL,
allocated_at datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
该表预先填充了可用代码,这些代码将分配给满足特定条件的订单。
我需要确保的是,在创建订单后,我获得可用的促销代码并更新其记录以反映它已被分配。
我不是 100% 确定如果同时请求进来,如何不两次抓取相同的记录。
我尝试在选择期间锁定行并在更新期间锁定行 - 两者似乎仍然允许第二次(同时)尝试抓取相同的记录 - 这是我想避免的
UPDATE promotion_code
SET allocated_at = "' . $db_now . '", order_id = ' . $donation->id . '
WHERE order_id IS NULL LIMIT 1
I have a table called promotion_codes
CREATE TABLE promotion_codes (
id int(10) UNSIGNED NOT NULL auto_increment,
created_at datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
code varchar(255) NOT NULL,
order_id int(10) UNSIGNED NULL DEFAULT NULL,
allocated_at datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
This table is pre-populated with available codes that will be assigned to orders that meet a specific criteria.
What I need to ensure is that after the ORDER is created, that I obtain an available promotion code and update its record to reflect that it has been allocated.
I am not 100% sure how to not grab the same record twice if simultaneous requests come in.
I have tried locking the row during a select and locking the row during a update - both still seem to allow a second (simultaneous) attempt to grab the same record - which is what I want to avoid
UPDATE promotion_code
SET allocated_at = "' . $db_now . '", order_id = ' . $donation->id . '
WHERE order_id IS NULL LIMIT 1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以添加第二个表来保存所有使用的代码。因此,您可以在分配表中使用唯一约束来确保一个代码不会被分配两次。
您将已使用的代码的 ID 添加到
used_codes
表中,然后查询您使用了哪些代码。当这两个操作在一个事务中时,当第二次尝试使用相同的代码时,整个事务将失败。下面的代码我没有测试,你可以调整一下。
此外,您还需要确保您的服务器满足事务要求< /a>.
如果交易成功,您可以使用返回的代码。如果有多个进程运行以使用相同的代码,则只有其中一个进程成功,而其余进程则因重复行的插入错误而失败。在您的软件中,您需要区分重复行错误和其他错误,并重新执行重复错误的语句。
You can add a second table which holds all used codes. So you can use an unique constraint in the assignment table to make sure that one code is not assigned twice.
You add the ID of an used code into the
used_codes
table, and query which code you used afterwards. When this two operations are in one transaction, the entire transaction will fail when there is a second try to use the same code.I did not test the following code, you might to adjust it.
Also you need to make sure that you have your server meets the requirements for transactions.
You can use the returned code if the transaction sucseeded. If there where more than one processes running to use the same code, only one of them succed, while the rest fails with insert errors about the duplicated row. In your software you need to distinguish between the duplicated row error and other errors, and reexecute the statement on duplication errors.