Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Добавление строки при параллельных запросах / 23 сообщений из 23, страница 1 из 1
02.04.2015, 18:35:10
    #38925502
cybexx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
Здравствуйте.

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

Есть простая таблица

Код: sql
1.
2.
3.
4.
5.
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(10) NOT NULL,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



Задача простая: проверить существование юзера с конкретным ID, если такой есть, то получить эту запись и продолжить с ним работать, Если нет то - создаем.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
SESSION1
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from users where id = 1 for update;
Empty set (0.00 sec)

SESSION2
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from users where id = 1 for update;
Empty set (0.00 sec)

SESSION1
mysql> insert into users (id,`name`) values(1,'Pit');
.... ожидание .... 

SESSION2
mysql> insert into users (id,`name`) values(1,'Pit');
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

SESSION1
Query OK, 1 row affected (9.85 sec)



В реальности задача, конечно же другая и более сложная. Для более легкого понимания, я убрал все лишнее и оставить только минимальные условия, которые вызывают конфликт.
Основные условия таковы: идентификатор задается в скрипте, между select-ом и insert-ом достаточно времени, чтобы мог появился параллельный запрос.
...
Рейтинг: 0 / 0
03.04.2015, 18:46:18
    #38926663
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
Переоформлю пример в виде таблички для наглядности
SESSION1SESSION2mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from users where id = 1 for update;Empty set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> select * from users where id = 1 for update;Empty set (0.00 sec)mysql> insert into users (id,`name`) values(1,'Pit');.... ожидание .... mysql> insert into users (id,`name`) values(1,'Pit');ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transactionQuery OK, 1 row affected (9.85 sec)
...
Рейтинг: 0 / 0
03.04.2015, 19:00:35
    #38926675
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
За модельным примером (бессмысленным вообще до жути) потерялась собственно решаемая реально задача.
cybexxЗадача простая: проверить существование юзера с конкретным ID, если такой есть, то получить эту запись и продолжить с ним работать, Если нет то - создаем.
Если задача именно такова - то навылет непонятно, откуда лаг между проверкой наличия и вставкой при отсутствии. Вы явно что-то недоговариваете, причём важное. Возникают подозрения, что выбран в принципе неверный путь решения.
...
Рейтинг: 0 / 0
06.04.2015, 10:33:09
    #38927775
cybexx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
Akina,
Если вам не приходилось сталкиваться с такой задачей или вам трудно найти практическое применение задачи - вовсе не означает, что она "бессмысленная до жути"

Задача вполне реальная. Что в ней такого необычного, что вас смутило? Что id юзера задается во внешнем источнике?

Спасибо miksoft , что оформил в виде таблицы. Так действительно гораздо нагляднее.
...
Рейтинг: 0 / 0
06.04.2015, 11:54:53
    #38927844
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
cybexxЧто в ней такого необычного, что вас смутило?SELECT ... FOR UPDATE предназначен для SELECT, после которого будет выполнен именно UPDATE. У Вас после SELECT выполняется INSERT. Следовательно, у Вас неверен подход к решению задачи.

Я понимаю, что Вы выбрали какой-то путь решения задачи, и теперь, похоже, несмотря на его очевидную неправильность, будете с пеной у рта отстаивать его. Не советую - только зря время потеряете.
...
Рейтинг: 0 / 0
06.04.2015, 13:41:19
    #38927993
Alex_Ustinov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
cybexx,

дык первым селектом (без for update) проверьте есть ли запись, а что дальше - это уже дальше... (уровень "изоляции" и т.д.)
...
Рейтинг: 0 / 0
06.04.2015, 13:49:57
    #38928003
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
cybexxAkina,
Если вам не приходилось сталкиваться с такой задачей или вам трудно найти практическое применение задачи - вовсе не означает, что она "бессмысленная до жути"

Я тоже согласен с идиотизмом задачи.

Но в принципе тебе сюда:
https://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
...
Рейтинг: 0 / 0
06.04.2015, 13:51:16
    #38928005
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
...
Рейтинг: 0 / 0
06.04.2015, 13:53:00
    #38928010
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
MasterZivSERIALIZABLEдык у него и так SERIALIZABLE, иначе откуда бы взяться дедлоку?
...
Рейтинг: 0 / 0
06.04.2015, 14:11:56
    #38928045
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
tanglirMasterZivSERIALIZABLEдык у него и так SERIALIZABLE, иначе откуда бы взяться дедлоку?

Дедлоков не должно быть на SERIALIZABLE ...
...
Рейтинг: 0 / 0
07.04.2015, 07:53:24
    #38928704
cybexx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
MasterZiv,
Уровни изоляции стоят дефолтные.

Akina,
Я не собираюсь ничего доказывать и тем более с пеной у рта. У меня стоит задача, условия которые я привел еще в первом посте
Основные условия таковы: идентификатор задается в скрипте, между select-ом и insert-ом достаточно времени, чтобы мог появился параллельный запрос.
Я совсем не настаиваю, что мой вариант решения с SELECT FOR UPDATE идеальный, тем более я сам вижу что это дает ошибку. Просто другого варианта я пока не придумал, поэтому обратился на форум за помощью. Пока никто не предложил другого варианта. Предложите свое решение, буду благодарен.
...
Рейтинг: 0 / 0
07.04.2015, 07:55:23
    #38928706
cybexx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
MasterZiv,
Уровни изоляции стоят дефолтные.

Akina,
Я не собираюсь ничего доказывать и тем более с пеной у рта. У меня стоит задача, условия которые я привел еще в первом посте
Основные условия таковы: идентификатор задается в скрипте, между select-ом и insert-ом достаточно времени, чтобы мог появился параллельный запрос.
Я совсем не настаиваю, что мой вариант решения с SELECT FOR UPDATE идеальный, тем более я сам вижу что это дает ошибку. Просто другого варианта я пока не придумал, поэтому обратился на форум за помощью. Пока никто не предложил другого варианта. Предложите свое решение, буду благодарен
...
Рейтинг: 0 / 0
07.04.2015, 08:19:34
    #38928718
Alex_Ustinov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
cybexx,

чтение не блокирует на чтение, вот такая тофтология, поэтому вы эффекта от FOR UPDATE не получите.
FOR UPDATE просто "лочит" запись, чтобы ее никто не изменил. Вот так просто, если "на пальцах".
И только получив ошибку при UPDATE, вы сможете сказать пользователю - "запись уже редактируется"

т.е
1. Проверяете SELECT-ом c COUNT наличие записи
2. если нет - INSERT
3. если есть - следующая логика.
А того что вы хотите - оно вроде бы понятно, но в контексте - непонятно.
Опишите лучше так: "Два пользователя ..., один делает так-то..., другой..."
...
Рейтинг: 0 / 0
07.04.2015, 08:28:16
    #38928726
cybexx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
Уровни изоляции не помогают или я что-то не правильно делаю?

SESSION1SESSION2mysql> SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;Query OK 0 rows affected (0.00 sec)mysql> START TRANSACTION;Query OK 0 rows affected (0.00 sec)mysql> select * from users where id=1;Empty set (0.00 sec)mysql> SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;Query OK 0 rows affected (0.00 sec)mysql> START TRANSACTION;Query OK 0 rows affected (0.00 sec)mysql> select * from users where id=1;Empty set (0.00 sec)mysql> insert into users (id,`name`) values(1,'Pit');........mysql> insert into users (id,`name`) values(1,'Pit');ERROR 1213 (40001) Deadlock found when trying to get lock; try restarting transactionQuery OK 1 row affected (6.72 sec)
...
Рейтинг: 0 / 0
07.04.2015, 08:44:47
    #38928738
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
cybexxУровни изоляции не помогаютА чем вам тут сериалайз поможет? В первой транзакции болтается незакоммиченный ид=1, и пока она не определится, что с ним делать, вторая так и будет затыкаться...
...
Рейтинг: 0 / 0
07.04.2015, 09:00:54
    #38928745
cybexx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
tanglir,
Просто выше в ветке упоминались уровни изоляции и что SERIALIZABLE не даст дедлоков.

Похоже, что только блокировка всей таблицы поможет решить задачу.
...
Рейтинг: 0 / 0
07.04.2015, 09:10:41
    #38928759
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
cybexxдругого варианта я пока не придумал, поэтому обратился на форум за помощью. Пока никто не предложил другого варианта. Предложите свое решение, буду благодаренА Вы не даёте возможности это сделать! Вместо формулирования задачи Вы формулируете свою попытку её решения. И всё, что мы можем - это указывать на кривость этой попытки.

Почему - сначала проверить, и только потом, если нет, вставить? Гораздо более очевидное решение - безусловно вставить (если запись уже есть - вставка не выполнится, уникальные индексы не дадут), а потом безусловно получить.
...
Рейтинг: 0 / 0
07.04.2015, 10:54:08
    #38928896
Alex_Ustinov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
cybexx,

так опишите задачу, это при входе в систему пользователя? пытаетесь сделать авторегистрацию? или что?
...
Рейтинг: 0 / 0
07.04.2015, 11:38:36
    #38928992
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
[quot cybexx]MasterZiv,
Уровни изоляции стоят дефолтные.

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


так и решай свою задачу сам, чего ты сюда то пришел?
а не можешь -- придется доказывать.
...
Рейтинг: 0 / 0
07.04.2015, 12:38:25
    #38929101
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
cybexxtanglir,
Просто выше в ветке упоминались уровни изоляции и что SERIALIZABLE не даст дедлоков.

Похоже, что только блокировка всей таблицы поможет решить задачу.

Я предполагал, что SERIALIZABLE поможет, потому что по стандарту обязан.
Но я не уверен до конца, потому что я сам никогда не работал с SERIALIZABLE на MySQL.
SERIALIZABLE по идее и должен был бы блокировать таблицу целиком (или применять другие методы разрешения конфликтов, которые эквивалентны блокировке таблицы), но видимо он этого не делает.

Да, и ты бы мог применять генерацию новых ключей с помощью автоинкремента, а не в скрипте, автоматом проблем было бы меньше.

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

Твоя задача:
авторпроверить существование юзера с конкретным ID, если такой есть, то получить эту запись и продолжить с ним работать, Если нет то - создаем.

Ты должен был бы озаботиться проверкой существования пользователя с заданным логином, а не с заданным ID. ID ничего не значит, он должен работать только внутри системы.
...
Рейтинг: 0 / 0
07.04.2015, 12:44:55
    #38929117
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
MasterZivТы должен был бы озаботиться проверкой существования пользователя с заданным логином, а не с заданным ID. ID ничего не значит, он должен работать только внутри системы.Это, конечно, верно, но даже если заменить в постах ТСа "ид" на "логин", то в общем-то ничего не изменится - он точно так же будет натыкаться на дедлоки. Просто потому что работает так, как работает.
...
Рейтинг: 0 / 0
07.04.2015, 13:18:28
    #38929172
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
tanglirMasterZivТы должен был бы озаботиться проверкой существования пользователя с заданным логином, а не с заданным ID. ID ничего не значит, он должен работать только внутри системы.Это, конечно, верно, но даже если заменить в постах ТСа "ид" на "логин", то в общем-то ничего не изменится - он точно так же будет натыкаться на дедлоки. Просто потому что работает так, как работает.

Абсолютно согласен.
Но тогда автора топика бы не объявляли "странным" и, возможно, сразу бы дали ответ.
...
Рейтинг: 0 / 0
08.04.2015, 11:26:03
    #38930177
Alex_Ustinov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Добавление строки при параллельных запросах
есть еще именнованые псевдоблокировки, но это больше к раздельному Редактированию данных, как я понимаю.
Ф-и
GET_LOCK
RELEASE_LOCK
IS_FREE_LOCK
IS_USED_LOCK

как можно применить к вашему случаю - решать и знать вам.
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Добавление строки при параллельных запросах / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]