【问题标题】:MySQL selling database consistency: queued transactions?MySQL 销售数据库一致性:排队事务?
【发布时间】:2020-05-27 09:54:16
【问题描述】:

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

我有 3 张桌子

交易(id,created_date)

卡片(ID、姓名)

凭证(id、code、card_id、transaction_id)

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

因此,应用程序将根据所选卡选择凭证并根据数量限制,然后创建一个新交易并将 transaction_id 添加到所选凭证中,以将其标记为此次新交易的已购买卡。

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

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

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

提前致谢

【问题讨论】:

    标签: php mysql laravel transactions queue


    【解决方案1】:

    这是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,您的用户就不会注意到这一点。这在应用程序级别通常不称为“排队”,而是称为事务一致性。

    Laravel / eloquent makes this super easy。它会为您执行 START TRANSACTIONCOMMIT 以及 offers lockForUpdate()

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

    【讨论】:

    • 哦,我现在明白了,这似乎已经足够好了,你认为如果我启动一个 MySQL 过程会在我有多个查询要运行的情况下变得更好吗?以便通过将所有内容都放在一个连接中来节省时间,还是雄辩的交易本身就可以做到这一点?非常感谢您的回答!
    • 在存储过程中执行此操作不会对事务的工作方式产生任何影响;您仍然需要处理来自 Eloquent 或您的 SP 的交易。如果我是你,我只会使用 Eloquent:MySQL 存储过程 (a) 难以调试,并且 (b) 未编译,因此速度不会快多少。 (Oracle 和 SQL Server 存储过程已编译,因此速度更快。)
    • 非常感谢,我将在整个交易中使用 eloquent...
    猜你喜欢
    • 2021-10-30
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    相关资源
    最近更新 更多