Этот вопрос может быть более подходящим для администраторов баз данных (а я не администратор баз данных), но я постараюсь дать вам некоторые идеи о том, что происходит.
InnoDB фактически не блокирует всю таблицу, когда вы выполняете запрос на обновление. Что он делает, так это следующее: он устанавливает блокировку записи, которая не позволяет любой другой транзакции вставлять, обновлять или удалять строки, где значение coupons.user_id
равно NULL.
С вашим запросом на данный момент (который зависит от user_id, равного NULL), вы не можете иметь параллелизм, потому что ваша транзакция будет выполняться одна за другой, а не параллельно.
Даже индекс на вашем coupons.user_id
не поможет, потому что при установке блокировки InnoDB создаст для вас теневой индекс, если у вас его нет. Результат будет таким же.
Итак, если вы хотите увеличить пропускную способность, есть два варианта, о которых я могу подумать:
- Назначить пользователя на купон в асинхронном режиме. Поместите все запросы о назначении в очередь, затем обработайте очередь в фоновом режиме. Может не подходить для ваших бизнес-правил.
- Уменьшить количество заблокированных записей. Идея заключается в том, чтобы при выполнении обновления заблокировать как можно меньше записей. Для этого вы можете добавить в таблицу один или несколько индексированных столбцов, а затем использовать индекс в предложении
WHERE
запроса Update
.
Примером столбца является product_id или категория, может быть местоположение пользователя (страна, почтовый индекс).
тогда ваш запрос будет выглядеть примерно так:
ОБНОВЛЕНИЕ купонов SET user_id = WHERE product_id = user_id равен NULL LIMIT 1;
И теперь InnoDB будет блокировать только записи с product_id = <product_id>
. Таким образом, вы будете иметь параллелизм.
Надеюсь, это поможет!