Следующие действия - это то, что может произойти за сценой, и с помощью любой современной прикладной среды это довольно легко достичь.
Я предполагаю, что ваш сценарий:
- Два пользователя, вошедшие в вашу систему, говорят, что они
U1
и U2
- Выберите товар
- Доступен только один товар
- Они оба нажали Добавить в корзину / Купить сейчас / Оформить заказ
- Один пользователь будет обслуживаться, а другой пользователь будет уведомлен о том, что продукт больше не доступен
Предположим, T1
и T2
представляют наносекундное представление времени, когда они нажимали на кнопку оформления заказа. Вероятность того, что T1
и T2
равны друг другу, очень мала, но есть вероятность.
В вашем случае веб-сервер будет обслуживать оба запроса, сгенерированные пользователями, в двух разных потоках, TH1
и TH2
. Весьма маловероятно, поскольку в любой момент времени в вашей системе присутствуют сотни пользователей, но не исключено, что TH1
и TH2
обслуживаются двумя разными ядрами ЦП, при условии, что у вас более одного ядра.
Следовательно, оба TH1
и TH2
попытаются завладеть вашим Продуктом.
Теперь вам нужно иметь / вводить два атрибута (представьте как столбцы MySQL) для ваших PRODUCT
: VERSION
и CHECKED_OUT
.
И TH1
, и TH2
начнут свои собственные транзакции одновременно, скажем, TR1
и TR2
, предполагая, что в качестве ядра базы данных используется InnoDB.
Оба из TR1
и TR2
будут:
- Считайте
PRODUCT
из таблицы базы данных вместе с VERSION
и CHECKED_OUT
: {id: 1, version: 0, checked_out: 0, ...}
и передайте его на сервер.
- На сервере оба параметра
TR1
и TR2
увеличат значение VERSION
, которое было прочитано ранее, и выполнят оператор Update, сообщающий, что UPDATE PRODUCT SET CHECKED_OUT = 1, VERSION = 1 WHERE ID = 1 AND VERSION = 0
- DB заблокирует строку, выполнит
UPDATE
и вернет номер измененной строки последовательно, поскольку UPDATE
должен быть выполнен в одном потоке. Обратите внимание, что этот поток является собственным потоком БД, а не TR1
и TR2
.
- Здесь, если я предполагаю, что
TR1
, т. Е. TH1
был обслужен раньше TR2
, т. Е. TH2
потоком БД UPDATE
, тогда бизнес-логика, стоящая за TR1
, получит, что количество строк обновление равно 1, тогда как TR2
получит 0.
- Что, в свою очередь, означает, что
U1
получит возможность проверить продукт, тогда как U2
получит уведомление с хорошим извиняющимся сообщением.