MySQL 出售数据库一致性:排队的事务?

MySQL selling database consistency: queued transactions?

我正在尝试创建一个能够销售礼品卡的应用程序,但我担心数据的一致性,所以让我解释一下我的意思:

我有 3 张桌子

交易(id,created_date)

cards(id, name)

vouchers(id, code, card_id, transaction_id).

数据库包含很多卡和凭证,每张凭证属于一张卡。 用户会想要select一张卡购买并选择数量。

因此,应用程序将根据 selected 卡 select 凭单并根据数量限制,然后创建新交易并将 transaction_id 添加到 selected 代金券以将其标记为此次新交易的已购卡。

所以,我担心的是,如果多个用户在同一时间对同一张卡发送相同的购买请求,那么会不会发生数据冲突?解决这个问题的最佳方法是什么?

我目前正在为所有表使用 MySQL 8 Community Edition 和 InnoDB 引擎。

我正在寻找的是,我是否可以创建某种队列,在不发生冲突的情况下一个接一个地激活事务,即使这意味着用户将不得不等到轮到他们在队列中。

提前致谢

这是 MySQL transactions 的工作。使用 SQL 你可以做这样的事情。

START TRANSACTION;
SELECT id AS card_id FROM cards WHERE name = <<<<chosen name>>>> FOR UPDATE;
--do whatever it takes in SQL to complete the operation
COMMIT;

多个 php 进程,可能会尝试同时对 cards 的同一行执行某些操作。将 START TRANSACTIONSELECT ... FOR UPDATE 结合使用将通过让下一个进程等待第一个进程执行 COMMIT 来防止这种情况发生。

在内部,MySQL 有一个等待进程队列。只要您在执行 BEGIN TRANSACTION 之后立即执行 COMMIT,您的用户就不会注意到这一点。这在应用程序级别通常不称为 "queuing",而是事务一致性。

Laravel / eloquent makes this super easy. It does the START TRANSACTION and COMMIT for you, and offers lockForUpdate().

DB::transaction(function() {
    DB::table('cards')->where('name', '=', $chosenName)->lockForUpdate()->get();
    /* do whatever you need to do for your transaction */
});