Синхронизация запросов

Cardinal

Новичок
Синхронизация запросов

Подскажите пожалуйста как мне синхронизировать несколько запросов.

Пример:
Есть скрипт который вызывается клиентом
PHP:
$fp = fopen("log.inc", "a");
fwrite($fp, "process: ".$_GET['id']." start \n");
echo "start";
for ($i = 0; $i < 1000; $i++)
{
	for ($j = 0; $j < 1000; $j++)
	{
	}
}
echo "stop";
fwrite($fp, "process: ".$_GET['id']." stop \n");
fclose($fp);
Необходимо синхронизировать его выполнение. т.е. пока этот скрипт не выполнится до конца не обслуживать новые запросы к нему от клиента.

Скрипт который позволяет подать несколько запросов подряд
PHP:
for ($i = 1; $i < 10; $i++)
{
	$get_str = "?id={$i}";
	$arr = parse_url("http://server/"); 
	$nn = "\r\n"; 
	$host = $arr["host"]; 
	$ref = $arr["scheme"]."//$host"; 
	$path = $arr["path"];
	$post ="";
	$request = "GET $path{$get_str} HTTP/1.0" . $nn . 
			 "Referer: $ref" . $nn . 
			 "Content-Type: application/x-www-form-urlencoded" . $nn . 
			 "Content-Length: " . strlen($post) . $nn . 
			 "Host: $host" . $nn . 
			 "Accept: */*" . $nn .
			 $post .
			 "Connection: Close" . $nn . $nn;
	$fp = fsockopen($host, 80, &$errno, &$errstr, 30); 
	fputs($fp, $request); 
}
Сейчас log.inc выглядит вот так
process: 1 start
process: 2 start
process: 3 start
process: 4 start
process: 5 start
process: 6 start
process: 7 start
process: 8 start
process: 1 stop
process: 2 stop
process: 9 start
process: 3 stop
process: 6 stop
process: 4 stop
process: 5 stop
process: 7 stop
process: 8 stop
process: 9 stop

а нужно чтоб выглядел так:
process: 1 start
process: 1 stop
process: 2 start
process: 2 stop
...

Подскажите пожалуйста как это можно сделать без использования расширений ПХП таких как Semaphore, Shared Memory and IPC Functions.
 

phpcoder

Новичок
Re: Синхронизация запросов

Автор оригинала: Cardinal
PHP:
$fp = fopen("log.inc", "a");
flock($fp, LOCK_NB); // пока файл залочен и поинтер на него не закрыт в него писаться ничего не будет
fwrite($fp, "process: ".$_GET['id']." start \n");
echo "start";
for ($i = 0; $i < 1000; $i++)
{
	for ($j = 0; $j < 1000; $j++)
	{
	}
}
echo "stop";
fwrite($fp, "process: ".$_GET['id']." stop \n");
fclose($fp);
 

phprus

Moderator
Команда форума
phpcoder
Я считаю, что файл желательно разблокировать после того как писать в него закончили.
Cardinal
Почтиай [m]flock[/m] там написано как работает эта функция.
 

Cardinal

Новичок
за flock спасибо посмотрю,

но мне вообще то не совсем с файлами работать надо это я просто пример привел чтоб не голословно рассуждать. На самом деле мне надо что то похожее с БД сделать.

Если конкретно то нужно как то не дать одному и тому же пользователю обновить свой аакаунт во время обновления аккаунта. Ну т.е.

он послал запрос на изменение аккаунта
аккаунт изменяется
в это вермя он посылает еще один запрос на изменение аккаунта
этот новый запрос берет данные еще не изменившегося аккаунта и на их основе действует
потом записываеются данне от первого запроса
записываются данные от второго запроса

в итоге первый запрос как бы затирается.

Вот мне и надо чтобы скрипт по изменению аккаунта не стартовал пока не закончится предыдушее измение.

Можно конечно использовать фиктивный файл и использовать его как семофор т.е. залочен значит стоим ждем если не залочен то поехали...
но просто можно наврно как то попроще
 

phpcoder

Новичок
phprus, согласен, желательно, но не обязательно. Т.к. файл разблокируется автоматом командой fclose($fp);

Cardinal, можно завести к-н поле в базе тогда, показывающее, что запись залочена.
и , к примеру
while(запись_залочена){
sleep(1);
}
 

Cardinal

Новичок
Вариант с дополнительным полем мне не очень нравится т.к. увеличит трафик SQL запросов, что не желательно.

А какого-то универсального механизма не давать скрипту запускатся в ядре ПХП нет? Неужели нельзя забить какуюнить общую область памяти и писать в нее инфу?
 

hermit_refined

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

Cardinal

Новичок
hermit_refined
Мне нужно не пропустить ни одного изменения в данонм случае. Предположим под изменением понимаем инкремент рейтинга пользователя, тогда надо его изменить как по первому так и повторому запросу.

Вы как я понимаю хотели сказать что типа второе изменение это окончаетльное и первым можно пренебречь. Это нетак. (ну иначе сталбы я тут глупые вопросы задавать :) )
 

Андрейка

Senior pomidor developer
Предположим под изменением понимаем инкремент рейтинга пользователя
[sql]UPDATE table SET rating=rating+4 WHERE id=100[/sql]

или еще чего нибудь будем предполагать?
 

Cardinal

Новичок
конечно будем :)

допустим что надо в зависимотсти от рейтинга еще и разрешать какие-то действия.

например если рейтинг меньше 100 то разрешаем сделать приятное и повышаем рейтинг. Вот тогда при параллельных запросах пользователь сделаеть две приятности, хотя по логике имеет право на одну :) (думаю ему это не понравится)

Я поэтому и вопрос задал не про частный случай с MySQL а про стандартный механизм вообще (про идею так сказать). И пример по этому не на БД а с файлами т.к. мне нужно именно блокировать выполнение скрипта.

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

Вот в принципе не плохая идея семофоры и разделяемые области памяти но они не входят в ядро и я боюсь что у конечного хостера этого не будет. Ну на чем то они посторены эти семофоры, значит зачатки идеи все же есть и в ядре?
 

Cardinal

Новичок
Нет семофоров не будет :)

Предложение с flock впринципе хорошее только я думаю будет тормозить все. Работа с файловой системой штука тормозная

-~{}~ 16.11.06 10:39:

Автор оригинала: phpcoder
flock($fp, LOCK_NB); // пока файл залочен и поинтер на него не закрыт в него писаться ничего не будет
только не LOCK_NB, а LOCK_EX :)
 

StUV

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

Cardinal

Новичок
ну мускул вроде тоже транзакции поддерживает если INNI DB включить. дело не в этом.

я не могу понять почему в ПХП то нет стандартного механизма разрешения такой ситуации. Я сомневаюсь что я первый с такой проблемой столкнлуся неужели все ищут вот такие вот чатсные варианты.
 

С.

Продвинутый новичок
Автор оригинала: Cardinal
я не могу понять почему в ПХП то нет стандартного механизма разрешения такой ситуации. Я сомневаюсь что я первый с такой проблемой столкнлуся неужели все ищут вот такие вот чатсные варианты.
Потому что такие ситуации не входят в компетенцию ПХП. Это задача обработка данных (БД) и для этого там создан мехнизм транзакций, блокирования и пр. Как раз в рамках БД это совершенно стандартный вариант работы.
 

hermit_refined

Отшельник
например если рейтинг меньше 100 то разрешаем сделать приятное и повышаем рейтинг. Вот тогда при параллельных запросах пользователь сделаеть две приятности, хотя по логике имеет право на одну (думаю ему это не понравится)
[sql]UPDATE TABLE SET rating = rating + 1 WHERE id = 100 AND rating < 100[/sql]
т.к. мне нужно именно блокировать выполнение скрипта.
блокировать вообще? - т.е. когда обрабатывается один запрос, все параллельные запросы по-вашему должны блокироваться? в нормальных скриптах такого никогда не требуется.
встроенным сессиям свойственно блокировать параллельные запросы от того же пользователя, но и это - imho, зачастую неудобно.
А тут что-то все скатилось в частные случаи, жестко привязанные к конкретной задаче
потому что вам это надо в теории, а в реальных задачах это нечасто требуется...
я не могу понять почему в ПХП то нет стандартного механизма разрешения такой ситуации
...а тогда, когда требуется - необходимые блокировки должны устанавливаться на низшем уровне.
 

Cardinal

Новичок
С.
Синхронизция переменых это весьма распространенное явление в языках программирования. Да и в ПХП есть семафоры и разделяемая память (только почему-то не в ядре).

Т.е. мысли о том что это всетаки задача и ПХП напрашиваются.

-~{}~ 16.11.06 19:56:

hermit_refined
Я уже говорил выше. Для решения задачи мне подходят семафоры. Меня смущает что они не принадлежат к ядру ПХП.

Я надеюсь что Вы мне подскажите как реализовать их жалкое подобие самостоятельно, на функциях ядра.
 
Сверху