Параллельные потоки.

Vladislavik

Новичок
Параллельные потоки.

<?php
$time=time();

mysql_query("LOCK TABLES `base` WRITE;");

$sql=mysql_query("SELECT `timestamp` FROM `base` WHERE `id`='1' FOR UPDATE");
$stime=mysql_fetch_array($sql);
if($stime['timestamp']>=$time)
{}else
{
if($stime['timestamp']+30>=$time)
{}else
{
mysql_query("UPDATE `base` SET `timestamp`='".$time." WHERE `id`='1'");
//Полезная работа;
}
}
mysql_query("UNLOCK TABLES");

?>

Имеется таблица MyIsam.
Иногда случается ситуация, при которой практически одновременно 2 или более юзеров запускают скрипт и запрашивают timestamp, и происходит UPDATE timestamp'а и, соответственно, несколько раз выполняется "полезная работа".
Как избежать такой ситуации? Испробовал, как видно все и транзакции, и FOR UPDATE, и проверку на то, что timestamp больше time(). Все равно иногда обновление timestamp выполняется 2 а то и три раза.
 

Вурдалак

Продвинутый новичок
Re: Параллельные потоки.

Автор оригинала: Vladislavik
Иногда случается ситуация, при которой практически одновременно 2 или более юзеров запускают скрипт и запрашивают timestamp, и происходит UPDATE timestamp'а и, соответственно, несколько раз выполняется "полезная работа".
Описание подозрительно напоминает мою тему: http://phpclub.ru/talk/showthread.php?s=&threadid=116350
 

Vladislavik

Новичок
Re: Re: Параллельные потоки.

Автор оригинала: Вурдалак
Описание подозрительно напоминает мою тему: http://phpclub.ru/talk/showthread.php?s=&threadid=116350
Похоже, то похоже, я сначала Вашу тему читал и пробовал, но так понял, что надо переделать тип таблицы на Inobd, У вас ведь вышло с транзакциями и у Вас тип Inobd?
Просто оч хочется не переделывать тип таблицы с myisam. Может можно как то еще второй парралельный поток не пускать выполнять полезную работу?

-~{}~ 12.12.09 10:09:

Krishna, я только начинаю с PHP и mysql, можно по русски, что Вы хотели ссылками обьяснить?
 

stillwaiting

Новичок
Re: Параллельные потоки.


1. MyISAM не поддерживают транзакцию. Измените на InnoDB
2. Запретите 2-м и более потокам одновременно исполнять это место. Например, лочьте файл:
http://php.net/manual/en/function.flock.php , или же session_start() (по сути тоже лочит файл). Или программный лок средствами mysql:
http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock

UPDATE: перечитал топикастера, понял что все вышесказанное неактуально.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
мне одному кажется, что ТСу лишь бы пропустить ненужные апдейты, а все пишут какую-то чушь про трензакционную целостность?

если я прав, то делается это через кеширвание (APC/XCache/Eaccelerator/Memcached)
ключ - ID записи, значение - timestamp последнего обновления
и делать обновление после проверки
 

Вурдалак

Продвинутый новичок
Автор оригинала: grigori
мне одному кажется, что ТСу лишь бы пропустить ненужные апдейты, а все пишут какую-то чушь про трензакционную целостность?

если я прав, то делается это через кеширвание (APC/XCache/Eaccelerator/Memcached)
ключ - ID записи, значение - timestamp последнего обновления
и делать обновление после проверки
Чушь пишешь ты, кеширование тут никаким боком.

-~{}~ 12.12.09 23:32:

И, опять же, это всё костыли.
 

Vladislavik

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

<?
$block=mysql_query("SELECT GET_LOCK('users',0);");
//print_r(mysql_fetch_assoc($block));
if(mysql_result($block,0)== 1) {
//полезная работа, обновление timestamp;
}
mysql_query("SELECT RELEASE_LOCK('users');");
?>
 

Vladislavik

Новичок
Решаю задачу с тем, что мне нужно чтобы в определенное время один раз записалось в лог "update ячейка=1+ячейка", а при большом количестве запросов бывает, что update обновляется по несколько раз в секунду, в итоге должно было прибавить в лог в определенное время "1", а прибавило "3". Это, как я понял происходит из-за параллельных потоков, вот и пытаюсь от них избавиться.....
 

dimagolov

Новичок
колись дальше. зачем нужно делать "update ячейка=1+ячейка" но не чаще, чем раз в секунду?
 

vovanium

Новичок
Vladislavik
update ячейка=1+ячейка",
А что мешает написать типа
[sql]UPDATE `base` SET `timestamp`={$time}, `counter` = `counter`+1 WHERE `id`='1' AND `timestamp`!={$time}[/sql]
И будет тебе не больше одного обновления счетчика в секунду
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Вурдалак
а ты откуда знаешь?

если он хочет избавиться от лишних запросов, можно создавать файл-флаг и проверять таймстэмп
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
знаешь решение лучше - пиши
не знаешь - троллей тут не любят
 

Вурдалак

Продвинутый новичок
Решение — перейти на InnoDB.

Крайний случай — LOCK TABLES.

-~{}~ 14.12.09 03:39:

Автор оригинала: Vladislavik
Просто оч хочется не переделывать тип таблицы с myisam.
В InnoDB нет FULLTEXT-индексов, в остальном не вижу проблем.

-~{}~ 14.12.09 03:44:

Но и вряд ли тебе FULLTEXT-индекс понадобится в подобного рода таблице.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Вурдалак
а чем это решение лучше?
у ТСа проблема не в том, что юзеры выполняют запросы "практически одновременно"
т.е. ему мешают не одновременные запросы, а просто слишком частые
 

Вурдалак

Продвинутый новичок
Автор оригинала: grigori
у ТСа проблема не в том, что юзеры выполняют запросы "практически одновременно"
т.е. ему мешают не одновременные запросы, а просто слишком частые
Что за додумывания? По-моему, проблема описана в первом посте довольно понятно.
 

dimagolov

Новичок
Вурдалак, это не додумывание, а твое невнимание:
Автор оригинала: Vladislavik
Решаю задачу с тем, что мне нужно чтобы в определенное время один раз записалось в лог "update ячейка=1+ячейка", а при большом количестве запросов бывает, что update обновляется по несколько раз в секунду, в итоге должно было прибавить в лог в определенное время "1", а прибавило "3".
 

Вурдалак

Продвинутый новичок
Хорошо. Какая разница UPDATE больше нужного выполняется или INSERT в какую-то таблицу? Это лишь какой-то частный случай проблемы.
 
Сверху