MySQL продаж согласованности базы данных: транзакции в очереди? - PullRequest
1 голос
/ 27 мая 2020

Я пытаюсь создать приложение, которое может продавать подарочные карты, но я опасаюсь непротиворечивости данных, поэтому позвольте мне объяснить, что я имею в виду:

У меня есть 3 таблицы

транзакций (id, created_date) ,

карт (id, name) и

ваучеров (id, код, card_id, transaction_id) .

База данных содержит множество карт и ваучеров, и каждый ваучер принадлежит одной карте. Пользователь захочет выбрать карту для покупки и количество.

Таким образом, приложение выберет ваучеры в соответствии с выбранной картой и ОГРАНИЧЕНИЕ в соответствии с количеством, а затем создаст новую транзакцию и добавит transaction_id в выбранную ваучеры, чтобы пометить их как купленные карты для этой новой транзакции.

Итак, чего я боюсь, так это того, что если несколько пользователей отправят один и тот же запрос на покупку для одной и той же карты в одно и то же время, тогда произойдет конфликт данных произойти? и как лучше всего это исправить?

В настоящее время я использую MySQL 8 Community Edition с движком InnoDB для всех таблиц.

Я ищу, могу ли я создать несколько своего рода очередь, которая активирует транзакции одну за другой без конфликтов, даже если это означает, что пользователям придется ждать, пока они дойдут до своей очереди в очереди.

Заранее спасибо

1 Ответ

0 голосов
/ 27 мая 2020

Это задание для MySQL транзакций . С помощью 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 есть очередь ожидающих процессов. Пока вы выполняете COMMIT сразу после BEGIN TRANSACTION, ваши пользователи этого не заметят. Чаще всего это называется не «постановкой в ​​очередь» на уровне приложения, а согласованностью транзакций.

Laravel / eloquent делает это очень просто . Он выполняет START TRANSACTION и COMMIT за вас, а предлагает lockForUpdate().

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