Есть 2 таблицы: пользователи (user) и телефоны (phone). При добавлении нового пользователя (ввод номера телефона) проверяется, нет ли такого номера в БД phone:
SELECT COUNT(phone.id) FROM phone WHERE phone.number = '1234567';
Если номера телефона нет в БД, тогда выполняется вставка данных:
SELECT MAX(id) AS max_id FROM user
$newId = $maxId + 1;
INSERT INTO user (id, name) VALUES ('.$newId.', "Test")
INSERT INTO phone (id, user_id, number) VALUES (DEFAULT, '.$newId.' "1234567")
Подскажите, как правильно расставить блокировки на данные, чтобы не блокировать все таблицы (user и phone) для регистрации нового пользователя?
И так, наша задача заблокировать в таблице телефонов такую запись, что бы никто не мог в это время произвести вставку с таким же номером телефона. Если запись с таким номером уже есть, то все просто, достаточно было бы заблокировать ее. Но если записи нет, то блокировать нечего. Предлагаю в таком случае блокировать последнюю запись в таблице телефонов. Да, это приведет к блокировке всех, кто пытается добавить пользователя, но другого нормального пути нет. Запрос выполняющий это будет выглядеть так:
SELECT phone FROM phone
WHERE number = '1234567'
OR id=(select max(id) from phone)
ORDER BY id
LIMIT 1
FOR UPDATE
После запроса проверяем номер телефона, который он вернул. Если он совпадает с искомым, значит он уже есть и вставку делать не надо. Если не совпадает - значит получена (и заблокирована) последняя запись из таблицы, можно вставлять новые данные.
Обращаю ваше внимание, что использование select max(id)+1
для поиска id для новой записи потребует полной блокировки всей таблицы. Следует пользоваться auto_increment id. Вообще не указывая поле id в операции insert. После выполненной вставки вам будет доступна mysqli->insert_id, с только что вставленным значением. И в дальнейших операциях надо использовать его.
Так же обращаю ваше внимание, что фраза FOR UPDATE
в SQL запросе, производит блокировку, только если явно находитесь в транзакции. По этой причине убедитесь, что на соединении не включен режим auto commit. Блокировка на записи будет удерживаться вплоть до явного выполнения commit или rollback. Так что использовать их так же необходимо.
Добиться уникальности очень просто, и безо всяких блокировок. Достаточно просто сформулировать свою проблему. Поскольку само слово "уникальность" как бы намекает.
Достаточно добавить уникальный индекс на номер телефона. И, разумеется, вычистить весь тот ужас, который используется сейчас. Проблема решена.
Сначала надо сделать вставку в таблицу телефонов и обработать ошибку. В mysqli можно использовать ключевое слово ignore.
Если запись не вставилась - значит телефон уже есть, и никто никуда не идёт.
Если запись вставилась - только после этого создаем юзера, получаем человеческим способом user_id и обновляем строку с телефоном.
Для надежности можно все эти манипуляции завернуть в тарнзакцию.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Подскажите пожалуйста, есть ли у кого пример кода чтения и записи данных из/в открытый ексель файл с помощью COM/OLE на чистом С++
Столкнулся с интересным вопросом, причем ничего явно отвечающего на него в интернете не нашелСобственно, есть папка Program Files (x86)\Windows Kits/10/Include...