Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Запрет одновременного выполнения / 25 сообщений из 33, страница 1 из 2
15.04.2015, 16:13
    #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
15.04.2015, 16:28
    #38937430
-k2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрет одновременного выполнения
hated,

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


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

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

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

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

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


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

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

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

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

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

Не совсем вас понял... Вы о чём?
...
Рейтинг: 0 / 0
17.04.2015, 16:30
    #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
17.04.2015, 16:33
    #38939483
-k2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрет одновременного выполнения
hated,

mysql_query возвращает результат:
true - если ваш групид ставлен, false - если ваш групид не вставлен (например неуникален)
...
Рейтинг: 0 / 0
17.04.2015, 16:44
    #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
17.04.2015, 18:36
    #38939604
mini.weblab
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрет одновременного выполнения
по задаче:
пусть
Id: 1, 2, 3, NULL, 147, 148, NULL, 150, 151
твоя функция должна вернуть 4
так?
...
Рейтинг: 0 / 0
18.04.2015, 07:44
    #38939749
hated
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрет одновременного выполнения
mini.weblabпо задаче:
пусть
Id: 1, 2, 3, NULL, 147, 148, NULL, 150, 151
твоя функция должна вернуть 4
так?
ну да...
...
Рейтинг: 0 / 0
18.04.2015, 15:24
    #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
18.04.2015, 15:25
    #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
18.04.2015, 21:48
    #38939917
Karbafos
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрет одновременного выполнения
hated?пропущено...
Если у вас будет столько записей, что "айдишники кончаться будут", то первый запрос у вас будет час выполняться
Дак в том то и дело что непрерывно одни айдишники удаляюся(освобождаются) другие добавляются(берут освободившиеся айди).
сколько в сутки?
...
Рейтинг: 0 / 0
20.04.2015, 17:18
    #38940877
alex564657498765453
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрет одновременного выполнения
ответ был в самом первом посте.

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

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

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

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

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

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

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

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

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

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

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

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

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


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