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 TRANSACTION
与 SELECT ... 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 */
});
我正在尝试创建一个能够销售礼品卡的应用程序,但我担心数据的一致性,所以让我解释一下我的意思:
我有 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 TRANSACTION
与 SELECT ... 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 */
});