[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Предотвратить повторное обновление строки в таблиц
Страницы: 1, 2
Zuenf
Есть скрипт который каждую секунду получает данные с БД. Если данные каким-либо образом изменились, то необходимо обновить данную строку в таблице. Но проблема в том что этот скрипт работает у каждого пользователя. Т.е. два пользователя одновременно выбирают строку из БД видят что она изменилась и посылают два запроса на обновление. Как предотвратить второй запрос?

Для примера код:

$row = getRow("SELECT * FROM `table` WHERE `id` = 1");
if ($row['some'] == true) {
mysql_query("UPDATE `table` SET `rand` = ".rand(0, 1000)." WHERE `id` = {$row['id']}");
} else {
doSomething();
}
inpost
А зачем? Ничего не понял.

_____________
Обучаю веб-программированию качественно и не дорого: http://school-php.com
Фрилансер, принимаю заказы: PHP, JS, AS (видео-чаты). Писать в ЛС (Личные сообщения на phpforum).
Valick
что то у вас с логикой кода не лады
объясните подробнее в чём суть данных манипуляций

_____________
Стимулятор ~yoomoney - 41001303250491
Zuenf
Возможно не поняли потому что я забыл дописать WHERE в запросе выбора строки. Но суть я описал словами.

Попробую еще раз:
Если в строке установили ячейку some в true, то первый запрос от пользователя обновляет ячейку rand в этой строке. Но два или более пользователей могут получить одновременно информацию об этом изменении и соответственно обновить эту строку дважды. В этом и заключается проблема, нужно только одно обновление.

Немного измененный код:

$row = getRow("SELECT * FROM `table` WHERE `id` = 1 AND `rand`IS NULL "); //два пользователя выберут эту строку т.к. UPDATE еще не в очереди и соответственно обновят дважды
if ($row['some'] == true) {
mysql_query("UPDATE `table` SET `rand` = ".rand(0, 1000)." WHERE `id` = {$row['id']}");
} else {
doSomething();
}
inpost
Zuenf
Я правильно понимаю, что проблема у тебя в том:
Всего 2 запроса к БД, тут идут 2 запроса к скрипту, в итоге сначала отработает первый запрос к БД у первого человека, потом первый запрос у второго человека, и только потом второй запрос к БД ?
Если да, то тебе нужны блокировки чтения. http://habrahabr.ru/post/238513/
Если не ошибаюсь, то именно REPEATABLE READ.
Правда не уверен, что это всё можно провернуть через mysql запрос и нужен что-то вроде mysqli, но могу и бред сказать wink.gif

_____________
Обучаю веб-программированию качественно и не дорого: http://school-php.com
Фрилансер, принимаю заказы: PHP, JS, AS (видео-чаты). Писать в ЛС (Личные сообщения на phpforum).
Valick
500р решение без транзакций и блокировок

_____________
Стимулятор ~yoomoney - 41001303250491
Zuenf
Сорри это я на самом деле тупанул. Спасибо за ссылки в любом случае пригодятся.

Для большей наглядности примера изменил some на time_end, которое указывает когда стоит произвести обновление.
$row = getRow("SELECT * FROM `table` WHERE `id` = 1 AND `time_end` <= NOW() AND `rand` IS NULL"); 
if ($row) {//время истекло значит обновляем
mysql_query("UPDATE `table` SET `rand` = ".rand(0, 1000)." WHERE `id` = 1 AND `rand` IS NULL"); //обновляем если rand еще не установлен.
} else {
doSomething();
}
Valick
Цитата (Zuenf @ 26.06.2015 - 15:50)
"UPDATE `table` SET `rand` = ".rand(0, 1000)." WHERE `id` = 1 AND `rand` IS NULL"

при таком запросе и предыдущий вариант будет работать
после того как поле rand изменит значение с NULL на случайное, оно уже будет не NULL, следовательно все последующие запросы "в молоко"

логика с `time_end` еще страшнее первоначального варианта

_____________
Стимулятор ~yoomoney - 41001303250491
Zuenf
Цитата (Valick @ 26.06.2015 - 17:08)
Цитата (Zuenf @ 26.06.2015 - 15:50)
"UPDATE `table` SET `rand` = ".rand(0, 1000)." WHERE `id` = 1 AND `rand` IS NULL"

при таком запросе и предыдущий вариант будет работать
после того как поле rand изменит значение с NULL на случайное, оно уже будет не NULL, следовательно все последующие запросы "в молоко"

логика с `time_end` еще страшнее первоначального варианта

time_end логичнее, потому что в предыдущем варианте отдельный скрипт менял значение some на true и в тотже момент можно было бы установить этот самый rand, что исключило бы проблему. Потому и решил изменить.
Valick
Цитата (Zuenf @ 26.06.2015 - 16:20)
Логика с time_end логичнее

biggrin.gif
жду вашего следующего визита

_____________
Стимулятор ~yoomoney - 41001303250491
Zuenf
Цитата (Valick @ 26.06.2015 - 17:24)
Цитата (Zuenf @ 26.06.2015 - 16:20)
Логика с time_end логичнее

biggrin.gif
жду вашего следующего визита

Эх, одновременно заметили))
AllesKlar
Zuenf
// особо не вникая в дебаты

В таблице поле - время последнего обновления.
Данные прочитали, известно время последнего обновления.
Пытамемся обновить, если данные в таблице имеют то же время последнего обновления, как и полученные до этого данные.
Если в таблице это поле уже имеет другое значение, значит данные были обновлены другим пользователем, значит перечитываем данные сначала.

$sql = 'SELECT id, feld, last_update FROM table';
.......

$id = $row['id'];
$last_update = $row['last_update'];
......

$sql = "UPDATE table SET feld = $new_data WHERE id = $id AND last_update = $last_update";
......

// проверка, изменились ли данные, зависит от библиотеки работы с DB
if( ! $is_data_update)
{
$sql = "SELECT id, feld, last_update FROM table";
......


}


_____________
[продано копирайтерам]
Zuenf
Цитата (AllesKlar @ 26.06.2015 - 18:49)
Zuenf
// особо не вникая в дебаты

В таблице поле - время последнего обновления.
Данные прочитали, известно время последнего обновления.
Пытамемся обновить, если данные в таблице имеют то же время последнего обновления, как и полученные до этого данные.
Если в таблице это поле уже имеет другое значение, значит данные были обновлены другим пользователем, значит перечитываем данные сначала.

$sql = 'SELECT id, feld, last_update FROM table';
.......

$id = $row['id'];
$last_update = $row['last_update'];
......

$sql = "UPDATE table SET feld = $new_data WHERE id = $id AND last_update = $last_update";
......

// проверка, изменились ли данные, зависит от библиотеки работы с DB
if( ! $is_data_update)
{
$sql = "SELECT id, feld, last_update FROM table";
......


}

Ну если вы хотели ответить на мой изначальный вопрос, то к сожалению не получилось. Т.к. первый запрос 'SELECT id, feld, last_update FROM table' может вывести одновременно двум пользователь один и тот же last_update. Т.е. и один и второй получат например 26.08.2015 18:05:13. И далее последуют одинаковые действия т.к. исходные данные одинаковые. Это надо делать на уровне самой БД, т.е. если уже один запрос на обновление прошел то следующий стоящий в очереди не выполнять.
Миша
А если доп.поле с временем,

в условии обновить, если текукее время больше, чем в таблице

_____________
Принимаю заказы, писать в ЛС
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.