MySQL InnoDB блокирует только затронутые строки?
-
22-09-2019 - |
Вопрос
У меня есть таблица InnoDB, содержащая пользователей, вот так:
+--------------+-----------------------+
| user_id | name |
+--------------+-----------------------+
| 1 | Bob |
| 1 | Marry |
| 2 | Bob |
| 1 | John |
| 3 | Bob |
| 2 | Marry |
+--------------+-----------------------+
При каждой вставке я увеличиваю user_id на 1, так что, например, следующий user_id для Bob будет равен 4
Я использую этот запрос, чтобы сделать это:
INSERT INTO users (user_id, name)
SELECT 1 + coalesce((SELECT max(user_id) FROM users WHERE name='Bob'), 0), 'Bob';
Теперь мне нужно убедиться, что два разных пользователя не добавляют 'Bob' одновременно.Мне не нужны никакие два Bobs с user_id 4.Каждый из идентификаторов пользователя Bob должен отличаться.
Возможно ли записать и обновить блокировку всех строк Боба при выполнении приведенного выше запроса insert?Я не могу заблокировать всю таблицу целиком, потому что многим другим пользователям все еще нужен полный доступ к своим строкам.Кроме того, все строки должны быть доступны для чтения в любое время.Как бы я это сделал?
Решение
Предполагая, что InnoDB здесь, вы можете использовать ВЫБЕРИТЕ ...БЛОКИРОВКА В РЕЖИМЕ ОБЩЕГО ДОСТУПА чтобы заблокировать строки при их выборе.
Другие советы
Чтобы решить первую часть вашего вопроса, создайте уникальный индекс для идентификатора пользователя и имени.
alter table `users` add unique index ak_user_id_name(user_id,name);
Это предотвратит дублирование записей user_id,name.
Ответ на этот вопрос такой же , как этот.InnoDB заблокирует здесь больше строк, чем вы ожидаете, в целях безопасности с помощью двоичного ведения журнала на основе инструкций.
Решение: используйте двоичное ведение журнала на основе строк с уровнем изоляции, зависящим от чтения.