Я довольно новичок в использовании InnoDB
, используя свои механизмы блокировки, и я столкнулся с проблемой, о которой я не очень уверен.Правильно блокировка строк во время процедуры регистрации пользователя
Представьте, что вы создаете систему SIGNUP вообще, так что пользователь пытается зарегистрировать и вы сделать что-то вроде этого, чтобы проверить, если их имя пользователя они хотели доступно:
SELECT COUNT(*) FROM users WHERE username='$username';
Затем выяснить имя пользователя доступно так что вы идете вперед и сделать это:
INSERT INTO users(username,email) VALUES('$username','$email');
Теперь, что происходит, что в очень маловероятно, но возможно, что при какой-либо другой процесс проверки на то же имя пользователя перед тем вы вставили их в ДАТ и они получили одобрение - очевидно, мы не хотим, чтобы в итоге с двумя пользователями с тем же именем мы сделали !?
Так я думал, используя FOR UPDATE
замок, чтобы предотвратить это, что-то вроде:
autocommit=0;
SELECT COUNT(*) FROM users WHERE username='$username" FOR UPDATE;
INSERT INTO users(username,email) VALUES('$username','$email');
commit();
Однако я тогда понял, по крайней мере, от того, что я понимаю, что это не будет работать, потому что это только блокирует строки что SELECT
найдено; и поскольку он является COUNT
, он не ссылается ни на какие конкретные строки, и даже если вы изменили его на не используя COUNT
, он все равно не будет ссылаться ни на какие строки, поскольку имя пользователя не будет найдено.
Если это правильно, и это не сработает, единственное, что я могу придумать, это блокировка уровня таблицы, чтобы другие процессы не читали или не записывали в таблицу, но я знаю, что блокировки на уровне таблицы очень плохи и должны избегать.
Есть ли лучший способ сделать то, что я хочу сделать, не используя блокировки на уровне таблицы?
Да, я думал об этом, но мне не понравился факт создания общего сообщения об ошибке; но я думаю, что я могу найти определенные ключевые слова в ошибке mysql, чтобы проверить, пытались ли они вставить дублируемое имя пользователя или адрес электронной почты. О, и да, я знаю, чтобы использовать параметризованные запросы, просто сделал это, как это для примера :) – Brett