|
|
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Сходу задача кажется довольно банальная и, наверняка, обсуждалась много раз. Но я, к сожалению, не нашел решения. (Если плохо искал, пожалуйста, дайте конкретную ссылку) Есть простая таблица Код: sql 1. 2. 3. 4. 5. Задача простая: проверить существование юзера с конкретным 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. В реальности задача, конечно же другая и более сложная. Для более легкого понимания, я убрал все лишнее и оставить только минимальные условия, которые вызывают конфликт. Основные условия таковы: идентификатор задается в скрипте, между select-ом и insert-ом достаточно времени, чтобы мог появился параллельный запрос. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2015, 18:35:10 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
Переоформлю пример в виде таблички для наглядности 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) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2015, 18:46:18 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
За модельным примером (бессмысленным вообще до жути) потерялась собственно решаемая реально задача. cybexxЗадача простая: проверить существование юзера с конкретным ID, если такой есть, то получить эту запись и продолжить с ним работать, Если нет то - создаем. Если задача именно такова - то навылет непонятно, откуда лаг между проверкой наличия и вставкой при отсутствии. Вы явно что-то недоговариваете, причём важное. Возникают подозрения, что выбран в принципе неверный путь решения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2015, 19:00:35 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
Akina, Если вам не приходилось сталкиваться с такой задачей или вам трудно найти практическое применение задачи - вовсе не означает, что она "бессмысленная до жути" Задача вполне реальная. Что в ней такого необычного, что вас смутило? Что id юзера задается во внешнем источнике? Спасибо miksoft , что оформил в виде таблицы. Так действительно гораздо нагляднее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2015, 10:33:09 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
cybexxЧто в ней такого необычного, что вас смутило?SELECT ... FOR UPDATE предназначен для SELECT, после которого будет выполнен именно UPDATE. У Вас после SELECT выполняется INSERT. Следовательно, у Вас неверен подход к решению задачи. Я понимаю, что Вы выбрали какой-то путь решения задачи, и теперь, похоже, несмотря на его очевидную неправильность, будете с пеной у рта отстаивать его. Не советую - только зря время потеряете. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2015, 11:54:53 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
cybexx, дык первым селектом (без for update) проверьте есть ли запись, а что дальше - это уже дальше... (уровень "изоляции" и т.д.) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2015, 13:41:19 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
cybexxAkina, Если вам не приходилось сталкиваться с такой задачей или вам трудно найти практическое применение задачи - вовсе не означает, что она "бессмысленная до жути" Я тоже согласен с идиотизмом задачи. Но в принципе тебе сюда: https://dev.mysql.com/doc/refman/5.0/en/lock-tables.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2015, 13:49:57 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2015, 13:51:16 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
MasterZivSERIALIZABLEдык у него и так SERIALIZABLE, иначе откуда бы взяться дедлоку? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2015, 13:53:00 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
tanglirMasterZivSERIALIZABLEдык у него и так SERIALIZABLE, иначе откуда бы взяться дедлоку? Дедлоков не должно быть на SERIALIZABLE ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.04.2015, 14:11:56 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
MasterZiv, Уровни изоляции стоят дефолтные. Akina, Я не собираюсь ничего доказывать и тем более с пеной у рта. У меня стоит задача, условия которые я привел еще в первом посте Основные условия таковы: идентификатор задается в скрипте, между select-ом и insert-ом достаточно времени, чтобы мог появился параллельный запрос. Я совсем не настаиваю, что мой вариант решения с SELECT FOR UPDATE идеальный, тем более я сам вижу что это дает ошибку. Просто другого варианта я пока не придумал, поэтому обратился на форум за помощью. Пока никто не предложил другого варианта. Предложите свое решение, буду благодарен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 07:53:24 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
MasterZiv, Уровни изоляции стоят дефолтные. Akina, Я не собираюсь ничего доказывать и тем более с пеной у рта. У меня стоит задача, условия которые я привел еще в первом посте Основные условия таковы: идентификатор задается в скрипте, между select-ом и insert-ом достаточно времени, чтобы мог появился параллельный запрос. Я совсем не настаиваю, что мой вариант решения с SELECT FOR UPDATE идеальный, тем более я сам вижу что это дает ошибку. Просто другого варианта я пока не придумал, поэтому обратился на форум за помощью. Пока никто не предложил другого варианта. Предложите свое решение, буду благодарен ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 07:55:23 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
cybexx, чтение не блокирует на чтение, вот такая тофтология, поэтому вы эффекта от FOR UPDATE не получите. FOR UPDATE просто "лочит" запись, чтобы ее никто не изменил. Вот так просто, если "на пальцах". И только получив ошибку при UPDATE, вы сможете сказать пользователю - "запись уже редактируется" т.е 1. Проверяете SELECT-ом c COUNT наличие записи 2. если нет - INSERT 3. если есть - следующая логика. А того что вы хотите - оно вроде бы понятно, но в контексте - непонятно. Опишите лучше так: "Два пользователя ..., один делает так-то..., другой..." ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 08:19:34 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
Уровни изоляции не помогают или я что-то не правильно делаю? 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) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 08:28:16 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
cybexxУровни изоляции не помогаютА чем вам тут сериалайз поможет? В первой транзакции болтается незакоммиченный ид=1, и пока она не определится, что с ним делать, вторая так и будет затыкаться... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 08:44:47 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
tanglir, Просто выше в ветке упоминались уровни изоляции и что SERIALIZABLE не даст дедлоков. Похоже, что только блокировка всей таблицы поможет решить задачу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 09:00:54 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
cybexxдругого варианта я пока не придумал, поэтому обратился на форум за помощью. Пока никто не предложил другого варианта. Предложите свое решение, буду благодаренА Вы не даёте возможности это сделать! Вместо формулирования задачи Вы формулируете свою попытку её решения. И всё, что мы можем - это указывать на кривость этой попытки. Почему - сначала проверить, и только потом, если нет, вставить? Гораздо более очевидное решение - безусловно вставить (если запись уже есть - вставка не выполнится, уникальные индексы не дадут), а потом безусловно получить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 09:10:41 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
cybexx, так опишите задачу, это при входе в систему пользователя? пытаетесь сделать авторегистрацию? или что? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 10:54:08 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
[quot cybexx]MasterZiv, Уровни изоляции стоят дефолтные. Akina, Я не собираюсь ничего доказывать и тем более с пеной у рта. У меня стоит задача, условия которые я привел еще в первом посте так и решай свою задачу сам, чего ты сюда то пришел? а не можешь -- придется доказывать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 11:38:36 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
cybexxtanglir, Просто выше в ветке упоминались уровни изоляции и что SERIALIZABLE не даст дедлоков. Похоже, что только блокировка всей таблицы поможет решить задачу. Я предполагал, что SERIALIZABLE поможет, потому что по стандарту обязан. Но я не уверен до конца, потому что я сам никогда не работал с SERIALIZABLE на MySQL. SERIALIZABLE по идее и должен был бы блокировать таблицу целиком (или применять другие методы разрешения конфликтов, которые эквивалентны блокировке таблицы), но видимо он этого не делает. Да, и ты бы мог применять генерацию новых ключей с помощью автоинкремента, а не в скрипте, автоматом проблем было бы меньше. В том идиотизм твоей задачи и заключается -- ты в скрипте генерируешь идентификатор, и проверяешь наличие его в БД, а если нет -- именно с ним вставляешь запись, но вместе с тем имеешь конфликты. Значит, твой идентификатор несёт какую-то смысловую нагрузку из предметной области, а это недопустимо для идентификаторов, которые служат первичным ключём. Твоя задача: авторпроверить существование юзера с конкретным ID, если такой есть, то получить эту запись и продолжить с ним работать, Если нет то - создаем. Ты должен был бы озаботиться проверкой существования пользователя с заданным логином, а не с заданным ID. ID ничего не значит, он должен работать только внутри системы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 12:38:25 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
MasterZivТы должен был бы озаботиться проверкой существования пользователя с заданным логином, а не с заданным ID. ID ничего не значит, он должен работать только внутри системы.Это, конечно, верно, но даже если заменить в постах ТСа "ид" на "логин", то в общем-то ничего не изменится - он точно так же будет натыкаться на дедлоки. Просто потому что работает так, как работает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 12:44:55 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
tanglirMasterZivТы должен был бы озаботиться проверкой существования пользователя с заданным логином, а не с заданным ID. ID ничего не значит, он должен работать только внутри системы.Это, конечно, верно, но даже если заменить в постах ТСа "ид" на "логин", то в общем-то ничего не изменится - он точно так же будет натыкаться на дедлоки. Просто потому что работает так, как работает. Абсолютно согласен. Но тогда автора топика бы не объявляли "странным" и, возможно, сразу бы дали ответ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.04.2015, 13:18:28 |
|
||
|
Добавление строки при параллельных запросах
|
|||
|---|---|---|---|
|
#18+
есть еще именнованые псевдоблокировки, но это больше к раздельному Редактированию данных, как я понимаю. Ф-и GET_LOCK RELEASE_LOCK IS_FREE_LOCK IS_USED_LOCK как можно применить к вашему случаю - решать и знать вам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.04.2015, 11:26:03 |
|
||
|
|

start [/forum/topic.php?fid=47&msg=38925502&tid=1833341]: |
0ms |
get settings: |
7ms |
get forum list: |
14ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
42ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
56ms |
get tp. blocked users: |
1ms |
| others: | 205ms |
| total: | 338ms |

| 0 / 0 |
