powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Запрет одновременного выполнения
33 сообщений из 33, показаны все 2 страниц
Запрет одновременного выполнения
    #38937394
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте, прошу помощи...
В общем есть функция создающая новый ID соответствующий минимальному несуществующему.

function newPhonesGroup()
{
$minId = mysql_result(mysql_query("SELECT MIN(NULLIF(R1.groupid + 1, R2.groupid)) as mid FROM (SELECT groupid FROM phonesgroup UNION SELECT 0) R1 LEFT OUTER JOIN phonesgroup R2 ON R2.groupid = (R1.groupid + 1) OR R2.groupid IS NULL"),0,'mid');
mysql_query("insert into phonesgroup(groupid,cdate)values($minId,'".date('Y-m-d [H:i:s]')."')");
return $minId;
}


Первый запрос ищет минимальный ID из несуществующих в таблице phonesgroup, второй записывает его в эту таблицу.

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

Как можно этого избежать?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38937430
Фотография -k2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated,

присваивать ID при инсерте, не использовать конструкции вида +1, autoincrement
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38937471
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Но мне нужен минимальный из пустых ID как это сделать? Иначе у меня каждый месяц айдишники кончаться будут)
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38937493
Фотография -k2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated,


не вызывать функцию из разных скриптов :)
заморачиваться с блокировками в хранимке
уникальность по полю+завернуть в транзакцию, при получении ошибки перевыбрать номер ну и тому подобную чушь :)

часто оказывается нахождение пропусков пропусков в нумерации не такая необходимая вещь,
и тешит только глаз программиста, когда смотришь на эти красивые подряд идущие циферки :)
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38937495
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hatedНо мне нужен минимальный из пустых ID как это сделать? Иначе у меня каждый месяц айдишники кончаться будут)
Значит не пользуйся суррогатными ключами. Используй естественный ключ.
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38937498
Фотография -k2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да ещё видела маразм

генерировать табличку с диапазоном номеров и делать к ней привязку - нет привязки -> свободная касса
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38937507
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как думаете если после второго запроса добавить рекурсию
if (!mysql_affected_rows()) return newPhonesGroup();
Это решит проблему?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38937891
?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
?
Гость
hatedНо мне нужен минимальный из пустых ID как это сделать? Иначе у меня каждый месяц айдишники кончаться будут)Если у вас будет столько записей, что "айдишники кончаться будут", то первый запрос у вас будет час выполняться
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38938054
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
?hatedНо мне нужен минимальный из пустых ID как это сделать? Иначе у меня каждый месяц айдишники кончаться будут)Если у вас будет столько записей, что "айдишники кончаться будут", то первый запрос у вас будет час выполняться
Дак в том то и дело что непрерывно одни айдишники удаляюся(освобождаются) другие добавляются(берут освободившиеся айди).
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38938196
Barlone
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated?пропущено...
Если у вас будет столько записей, что "айдишники кончаться будут", то первый запрос у вас будет час выполняться
Дак в том то и дело что непрерывно одни айдишники удаляюся(освобождаются) другие добавляются(берут освободившиеся айди).Ну если генерировать по одному id в секунду, int переполнится через больше чем 60 лет. А если взять bigint, то можно по миллиону id в секунду выдавать в течении ста тысяч лет...
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939333
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hatedКак думаете если после второго запроса добавить рекурсию
if (!mysql_affected_rows()) return newPhonesGroup();
Это решит проблему?

НЕ ПОМОГЛО =( Сегодня опять обнаржил косяк...
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939415
Фотография -k2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated,

поле в базе уникальное?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939433
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В общем поступил радикально:
1) Перевел эту таблицу из MyISAM в InnoDB;
2) Сделал блокировку
mysql_query("LOCK TABLES phonesgroup WRITE");
.........
mysql_query("UNLOCK TABLES");


Кто подскажет, поможет ли это и какие могут быть побочки?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939436
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-k2-hated,

поле в базе уникальное?

Да - а толку...
Функция должна генерировать и записывать в phonesgroup уникальный groupid. Но нет-нет вижу случаи когда при работе в одно и то же время она отдает разным потокам один и тот же...
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939441
Фотография -k2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated,

а где у вас проверка на код возврата mysql_query("insert into phonesgroup(groupid,cdate)values($minId,'".date('Y-m-d [H:i:s]')."')"); ?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939460
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-k2-hated,

а где у вас проверка на код возврата mysql_query("insert into phonesgroup(groupid,cdate)values($minId,'".date('Y-m-d [H:i:s]')."')"); ?

Не совсем вас понял... Вы о чём?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939480
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Чет я совсем запутался так вообще работать не хочет возвращает пустое значение:
function newPhonesGroup()
{
mysql_query("LOCK TABLES phonesgroup WRITE");
$minId = mysql_result(mysql_query("SELECT MIN(NULLIF(R1.groupid + 1, R2.groupid)) as mid FROM (SELECT groupid FROM phonesgroup UNION SELECT 0) R1 LEFT OUTER JOIN phonesgroup R2 ON R2.groupid = (R1.groupid + 1) OR R2.groupid IS NULL"),0,'mid');
mysql_query("insert into phonesgroup(groupid,cdate)values($minId,'".date('Y-m-d [H:i:s]')."')");
mysql_query("UNLOCK TABLES");

return $minId;
}


Как сделать так, чтобы пока работает эта функция все остальные потоки пытающиеся её запустить - ожидали её окончания?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939483
Фотография -k2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated,

mysql_query возвращает результат:
true - если ваш групид ставлен, false - если ваш групид не вставлен (например неуникален)
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939488
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-k2-hated,

mysql_query возвращает результат:
true - если ваш групид ставлен, false - если ваш групид не вставлен (например неуникален)

Хм - стыдно... Я об этом не подумал начал mysql_affected_rows для этого юзать...
Ладно пусть тогда сейчас так поработает:

function newPhonesGroup()
{
$minId = mysql_result(mysql_query("SELECT MIN(NULLIF(R1.groupid + 1, R2.groupid)) as mid FROM (SELECT groupid FROM phonesgroup UNION SELECT 0) R1 LEFT OUTER JOIN phonesgroup R2 ON R2.groupid = (R1.groupid + 1) OR R2.groupid IS NULL"),0,'mid');
if (!$minId || !mysql_query("insert into phonesgroup(groupid,cdate)values($minId,'".date('Y-m-d [H:i:s]')."')"))
{
sleep(1);
return newPhonesGroup();
}

return $minId;
}


Может в сумме с InnoDB - косяки пропадут...
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939604
mini.weblab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
по задаче:
пусть
Id: 1, 2, 3, NULL, 147, 148, NULL, 150, 151
твоя функция должна вернуть 4
так?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939749
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mini.weblabпо задаче:
пусть
Id: 1, 2, 3, NULL, 147, 148, NULL, 150, 151
твоя функция должна вернуть 4
так?
ну да...
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939819
mini.weblab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated,

1) Если используешь локи на таблицы, то на InnoDB переходить не нужно
2) Это твоя база? Ты имеешь право таблицы лочить?
3) советую проверить успешность выполнение запросов
примерно так:

$res = mysql_query($some_query);
if(!res)
die ("Database access failed: " . mysql_error());

или менее сурово:

if(!res)
echo ("Database access failed: " . mysql_error());
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939820
mini.weblab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mini.weblab,
поправка

$res = mysql_query($some_query);
if(!$res)
die ("Database access failed: " . mysql_error());

или менее сурово:

if(!$res)
echo ("Database access failed: " . mysql_error());
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38939917
Фотография Karbafos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated?пропущено...
Если у вас будет столько записей, что "айдишники кончаться будут", то первый запрос у вас будет час выполняться
Дак в том то и дело что непрерывно одни айдишники удаляюся(освобождаются) другие добавляются(берут освободившиеся айди).
сколько в сутки?
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38940877
alex564657498765453
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ответ был в самом первом посте.

только вместо селескт трали-вали

инсерт инту табле селект-траливали

тоесть выборка и тутже вставка. паралельный изза уникальности поля(оно должно быть) уже выдаст ошибку, и тогда да повторно вставить.

насчёт того что один запрос будет выполняться час... ну формально, если бросать монетку (решка - выполниться первее другого, орёл - после) то шанс есть что 10000 раз выпадет решка. но с таким шансом и даже большим, у вас куча багов и ошибок на проекте.

а с другой стороны, если запросов столько что реальный шанс что какойто будет выполняться час, то вопрос - а вообще рационально из таблицы где за месяц айдишники заканчиваються(настолько нагруженная с ней работа) постоянно выборку минимального значения делать?

========
зы я бы не так делал, и начал бы с абсурдности поиска минимального айди.

абсурдности.
1)мы нашли минимальный 10, потенциальная проблема, что другой запрос тоже найдёт минимальный 10, вместо 11 - тогда возникает вопрос, разве не было бы решением если второй искал бы сразу не минимальное а 11. это явно автора устраивает, соответсвенно вопрос - так зачем мы исчём именно минимальное, а не просто любое значение которого нету?

2)вариант заканчивающегося за месяц айди, на фоне ГРУППЫ номеров(даже не номера) и максимальным значением 64битного числа представляеться абсурдом, особенно если учесть что можно брать ГУИД или подобное...128 битные значения, можно 256 битные значения.
не надо переживать изза возростающей нагрузки- костыли и руки из сопы куда более нагрузят базу.

3) сам запрос...он довольно таки тяжёллый. он вообще сколько времени на этой таблице выполняеться

4)каково назначение этого поля и записи в целом...почему вообще так получаеться, что на платёжных системах транкзанкции...даже на мировых системах, и айдишники для транкзанкций не заканчиваються, а у тебя для групы номеров заканчиваються(вот я пользуюсь системой где можно купить номер телефонный из группы, и на такую покупку есть транкзанкция....транкзанкций точно больше чем номеров груп, но у них не заканчиються)

(что-то мне кажеться, что это фанстическое предположение автора, что у него закончаться айди)

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

ТАК ЧТО автору надо менять изначальный подход с этими минимальными айди.
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38940910
mini.weblab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex564657498765453зы я бы не так делал, и начал бы с абсурдности поиска минимального айди.

абсурдности.
1)мы нашли минимальный 10, потенциальная проблема, что другой запрос тоже найдёт минимальный 10, вместо 11 - тогда возникает вопрос, разве не было бы решением если второй искал бы сразу не минимальное а 11. это явно автора устраивает, соответсвенно вопрос - так зачем мы исчём именно минимальное, а не просто любое значение которого нету?

а я бы посмотрела
a) на код где вы находите 11-й отсутствующий ID
б) на код где вы находите произвольный отсутствующий ID
с) давайте предполагать, что автор использовал SMALLINT для ID
=)
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38941224
alex564657498765453
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mini.weblabalex564657498765453зы я бы не так делал, и начал бы с абсурдности поиска минимального айди.

абсурдности.
1)мы нашли минимальный 10, потенциальная проблема, что другой запрос тоже найдёт минимальный 10, вместо 11 - тогда возникает вопрос, разве не было бы решением если второй искал бы сразу не минимальное а 11. это явно автора устраивает, соответсвенно вопрос - так зачем мы исчём именно минимальное, а не просто любое значение которого нету?

а я бы посмотрела
a) на код где вы находите 11-й отсутствующий ID
б) на код где вы находите произвольный отсутствующий ID
с) давайте предполагать, что автор использовал SMALLINT для ID
=)

с)и что, религия запрещает перейти на другой тип?
б)как два пальца об асфальт.даже без джоина,...сдесь на форуме уже были даже готовые примеры через переменные
а)вы не поняли мысли.... зачем акцент на минимальном айди, и как пример, второй процес сразу взял себе 11, а первый 10 потом- они искали не минимальный...но суммарный эффект как будто бы минимальный - явно не противоречит ТС, а следовательно - требования а минимальности не обязательное условия для решения задачи. ... это догматично показал на пальцах, что минимальность сдесь не нужна(ну либо ТС плохо описал что у него там проиходит)
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38941295
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
О! Оживление =)

В общем, не буду привязываться к цитатам отвечу в общем.
Да скорее всего я и погорячился - может не месяц, может даже не два и не год. Но!!! Это еще хуже, сейчас я знаю об этом узком месте и пытаюсь его оптимизировать, но забей я на это - в один прекрасный момент получаю баг, потери времени на исправление, потере на возмещение убытков простоя и т.д. Сейчас у нас 8 едентичных баз(разные города), кто знает сколько их будет через год-два... И уж тем более потом угадай в какой базе кончатся айдишники... Зачем эта бомба замедленного действия если вполне можно обойтись и без неё?...

Не отрицаю существование способов реализации более правильных и менее косячных и ресурсоемких. Но!!! Эта функция работает с 2011го года и косяки выявились только сейчас(и то редкие и не значительные), по нагрузке/времени работы нареканий нет... По этому смысла менять принцип работы и рисковать появлениями других багов(в случае если что-то забыл/не учел), лично я не вижу...

Итого:
От блокировок решил отказаться - побоялся и сделал как описал выше - перевел в Inno и делаю рекурсию если не произошла вставка.
function newPhonesGroup()
{
$minId = mysql_result(mysql_query("SELECT MIN(NULLIF(R1.groupid + 1, R2.groupid)) as mid FROM (SELECT groupid FROM phonesgroup UNION SELECT 0) R1 LEFT OUTER JOIN phonesgroup R2 ON R2.groupid = (R1.groupid + 1) OR R2.groupid IS NULL"),0,'mid');
if (!$minId || !mysql_query("insert into phonesgroup(groupid,cdate)values($minId,'".date('Y-m-d [H:i:s]')."')"))
{
sleep(1);
return newPhonesGroup();
}
return $minId;
}

Пока косяков не выявлено - как будут - обещаю Вас поставить в известность и быть более внимательным к вашим советам! =)
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38941306
alex564657498765453
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hatedО! Оживление =)

В общем, не буду привязываться к цитатам отвечу в общем.
Да скорее всего я и погорячился - может не месяц, может даже не два и не год. Но!!! Это еще хуже, сейчас я знаю об этом узком месте и пытаюсь его оптимизировать, но забей я на это - в один прекрасный момент получаю баг, потери времени на исправление, потере на возмещение убытков простоя и т.д. Сейчас у нас 8 едентичных баз(разные города), кто знает сколько их будет через год-два... И уж тем более потом угадай в какой базе кончатся айдишники... Зачем эта бомба замедленного действия если вполне можно обойтись и без неё?...

Не отрицаю существование способов реализации более правильных и менее косячных и ресурсоемких. Но!!! Эта функция работает с 2011го года и косяки выявились только сейчас(и то редкие и не значительные), по нагрузке/времени работы нареканий нет... По этому смысла менять принцип работы и рисковать появлениями других багов(в случае если что-то забыл/не учел), лично я не вижу...

Итого:
От блокировок решил отказаться - побоялся и сделал как описал выше - перевел в Inno и делаю рекурсию если не произошла вставка.
function newPhonesGroup()
{
$minId = mysql_result(mysql_query("SELECT MIN(NULLIF(R1.groupid + 1, R2.groupid)) as mid FROM (SELECT groupid FROM phonesgroup UNION SELECT 0) R1 LEFT OUTER JOIN phonesgroup R2 ON R2.groupid = (R1.groupid + 1) OR R2.groupid IS NULL"),0,'mid');
if (!$minId || !mysql_query("insert into phonesgroup(groupid,cdate)values($minId,'".date('Y-m-d [H:i:s]')."')"))
{
sleep(1);
return newPhonesGroup();
}
return $minId;
}

Пока косяков не выявлено - как будут - обещаю Вас поставить в известность и быть более внимательным к вашим советам! =)

дык что косяков пока не было?! Будут! пышли студент.
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38941401
hated
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alex564657498765453дык что косяков пока не было?! Будут! пышли студент.
Сплюньте! Ну их нафиг... =)
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38941448
mini.weblab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex564657498765453,

alex564657498765453 с)и что, религия запрещает перейти на другой тип?


ну, во-первых, в общем-то да, запрещает, особенно если не знаешь, кто, как и для чего еще использует базу
во вторых, с ограничениями интересней, а SMALLINT я просто так предположила, надо же с чего-то начать =)

alex564657498765453 а)вы не поняли мысли.... зачем акцент на минимальном айди, и как пример, второй процес сразу взял себе 11, а первый 10 потом- они искали не минимальный...но


ну может и не поняла, просто минимальный/максимальный найти легче (имхо).
поэтому было бы интересно посмотреть, как можно найти 11-й, 125-й

alex564657498765453 б)как два пальца об асфальт.даже без джоина,...сдесь на форуме уже были даже готовые примеры через переменные

ну вот я и говорю, что было бы интересно посмотреть код. тем более, что для вас это настолько просто
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38941454
mini.weblab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hated,
используй mysqli =)
...
Рейтинг: 0 / 0
Запрет одновременного выполнения
    #38942661
Фотография Karbafos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hatedЗачем эта бомба замедленного действия если вполне можно обойтись и без неё?...
как раз текущая реализация -- бомба. то, что скрипт работает с 2011 года не показатель.
в случае проблем тщательно скрывай свой адрес от тех, кто будет поддерживать систему после тебя.

ты занимаешься хренью, а не оптимизацией, меняй эту кривизну пока не поздно
...
Рейтинг: 0 / 0
33 сообщений из 33, показаны все 2 страниц
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Запрет одновременного выполнения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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