Параллельная запись в MySQL и тестирование решений - PullRequest
0 голосов
/ 26 февраля 2019

Я практиковал некоторые вопросы кодирования "системного проектирования", и меня интересовало, как решить проблему параллелизма в MySQL.Проблема заключалась в том, чтобы «разработать систему контроля запасов».

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

Если на веб-сайте два человека, желающие забронировать его, возможно ли, чтоони оба это проверили?Давайте предположим, что запрос обновляет состояние строки, чтобы пометить логическое значение checked_out до True.

Решат ли транзакции эту проблему?Это вызовет сбой второго запроса (при условии, что это один и тот же запрос).

В качестве альтернативы, мы вставляем строки в таблицу checkouts.Поскольку оба запроса читают, что элемент в настоящее время не извлечен, они могут быть оба вставлены в таблицу.Я не думаю, что транзакция решит эту проблему, если только транзакция не включает чтение таблицы, чтобы увидеть, существует ли в настоящее время проверка для этого элемента, который еще не закончился.

Один из предложенных методов

Как бы я смоделировал две записи одновременно, чтобы проверить это?

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Нет, только транзакции не решают проблемы параллелизма.Давайте быстро вернемся к определению транзакций mysql :

Транзакции - это атомарные единицы работы, которые можно зафиксировать или откатить.Когда транзакция вносит несколько изменений в базу данных, либо все изменения завершаются успешно, когда транзакция фиксируется, либо все изменения отменяются при откате транзакции.

Подводя итог: транзакцииспособ обеспечения целостности данных. СУБД

используют различные типы блокировка , уровни изоляции и решения на уровне подсистемы хранения для обеспечения параллелизма.Люди часто ошибочно принимают транзакции как средство управления параллелизмом, потому что транзакции влияют на то, как долго удерживаются определенные блокировки.

Сосредоточение на InnoDB: когда вы выполняете оператор update, mysql помещает эксклюзивная блокировка на обновляемой записи.Только транзакция, имеющая монопольную блокировку, может изменить данную запись, остальные должны ждать, пока транзакция не будет совершена.

Как это помогает вам предотвратить одновременное извлечение одной и той же книги несколькими пользователями?Допустим, у вас есть поле id, однозначно идентифицирующее книги, и поле checked_out, указывающее статус книги.

Вы можете использовать следующий атомный update, чтобы получить книгу:

update books set checked_out=1 where id=xxx and checked_out=0

Критерий checked_out=0 гарантирует, что update будет успешным, только если книга еще не выписана.Таким образом, если приведенный выше оператор влияет на строку, то текущий пользователь проверяет книгу.Если это не влияет ни на какие строки, тогда кто-то еще уже проверил книгу.Эксклюзивная блокировка гарантирует, что только одна транзакция может обновить запись в любой момент времени, тем самым сериализовав доступ к этой записи.

Если вы хотите использовать отдельную таблицу checkouts для резервирования книг, то вы можетеиспользуйте уникальный индекс идентификаторов книг, чтобы предотвратить повторное извлечение одной и той же книги.

0 голосов
/ 26 февраля 2019

Транзакции не приводят к сбою обновлений.Они вызывают сериализацию запросов.Только один метод доступа может выполнить последовательность запросов;другие ждут.

Все в SQL - это транзакция, включая операции обновления с одним оператором.Тип транзакции, обозначенный BEGIN TRANSACTION; ... COMMIT;, объединяет ряд запросов.

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

Это в целом правильно.Схемы оформления заказа должны всегда считывать доступность из базы данных.Цель транзакции состоит в том, чтобы избежать условий гонки, когда несколько пользователей пытаются извлечь один и тот же элемент.

SQL не имеет поточно-ориентированных атомарных инструкций тестирования и установки, как у многопоточных ядер процессора.Таким образом, вам нужно использовать транзакции для такого рода вещей.

Самая простая форма оформления заказа использует транзакцию, что-то вроде этого.

BEGIN TRANSACTION;
SELECT is_item_available, id FROM item WHERE catalog_number = whatever FOR UPDATE;
/* if the item is not available, tell the user and commit the transaction without update*/
UPDATE item SET is_item_available = 0 WHERE id = itemIdPreviouslySelected;
/* tell the user the checkout succeeded. */
COMMIT;

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

Более сложная схема оформления заказа, не описанная здесь, использует двухступенчатую систему.Первый шаг: транзакция для резервирования элемента для пользователя, отклонение резервирования, если кто-то еще его забронировал или зарезервировал.Второй шаг: у владельца резервирования есть фиксированное количество времени, чтобы принять бронирование и оформить заказ, либо срок действия бронирования истекает, и другой пользователь может зарезервировать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...