Форумы портала PHP.SU » » Работа с СУБД » Попытка избежать параллейного редактирования записи

Страниц (2): [1] 2 »
 

1. LEONeso - 27 Июня, 2011 - 02:27:57 - перейти к сообщению
Здравствуйте, хочу реализовать избежание параллейного редактирования одной и той же записи.

Логика:
1. Создаем переменную с датой и временем.
2. Отправляем запрос в БД на выдачу записи.
3. Сверяем созданную дату и запись в БД, если запись БД имеет пустую дату, то
3.1 выводим данные (после вывода, записываем дату конца редактирования записи (+5 минут)), если
3.2 дата записи БД имеет данные, то сверяем их с текущей датой (пункт 1), если
3.3 дата записи меньше, чем действительная, то выводим "просьбу повторить попытку позже" иначе
3.4 выдаем данные пользователю (после вывода, записываем дату конца редактирования записи (+5 минут)).

--
PS: Возможно стоит использовать сессию и проверять её существование, а не играть с датами?
2. DeepVarvar - 27 Июня, 2011 - 07:34:27 - перейти к сообщению
LEONeso MySQL имеет возможность блокировать таблицы?

Я делал так:
Создавал специальный лок-файл, в него ничего не пишется, из него ничего не читается.
Он просто блокируется. Дальше совершаем любые действия - меняем/удаляем/добавляем контент...
В конце снимаем с файла блокировку.
Пока скрипт залочивший файл не отработает - остальные будут стоять на очереди.
flock
3. LEONeso - 27 Июня, 2011 - 08:53:44 - перейти к сообщению
DeepVarvar, я так понял - в таком случае, пока человек не закончит редактирование записи страница не разблокируется? Я хочу учесть возможность человеческого фактора "всё бросить на пол пути и уйти" таким образом, проверка даты - это лучший вариант т.к. если микротайм покажет, что 5 минут уже прошли, тогда данные ему выведутся, тут дело в том, чтобы отдать запрос в бд, получить данные, сверить с доступностью и выдать сообщение или остальные данные из запроса. Всё делается в потоке - по моему достаточно рабочий вариант?
4. DeepVarvar - 27 Июня, 2011 - 09:36:34 - перейти к сообщению
LEONeso не надо забывать что мы всеже имеем дело с веб-приложениями.
Это не локально исполняемые приложения и их файлы.
Единственная синхронизация может быть какраз по дате, но она не очень хороша.
Типа, если кто-то нажал кнопку "редактировать", то в спецполе редактируемого материала нужно будет записать значение куки как ключ "текущего edit-хозяина".
По ней и проверять кто нажимал редактирование.
Так же стоит учесть момент что если "хозяин" отредактировав минут через 10-15 просто нажмет в браузере history.go(-1), передумает сохранять результат, кука не будет валидна для других "хозяев".
Поэтому нужно ставить лимит времени действия записанной в БД куки.
А это ты не угадаешь какое время поставить 5 мин? 20мин? 60???
Нехорошо...
Да и не видел я чтобы где-то так заморачивались разработчики.
Просто лочили и все.
5. LEONeso - 27 Июня, 2011 - 09:53:27 - перейти к сообщению
DeepVarvar, я наверное упустил самое главное - это отсутствия регистрации и данных о пользователях. Гостевой доступ к функции редактирования данных. В данном случае редактируются данные к изображениям, нажатием на изображение и подгрузкой обработанных данных в фрейм, дальнейшие действия уже идут через фрейм, где имеется форма ввода данных и кнопка для сохранения.

Если учитывать, что изображений на странице может быть несколько, то при нажатии на любое другое изображение, будут отсылаться $_get параметры в фрейм. От сюда и вывод необходимых данных с возможность их редактирования или их создание, в случае отсутствия данных, при сохранении записи, они создаются.

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

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

Зачем это надо?
- Одному человеку трудно проиндексировать (в данном случае 40000+ изображений), но если нас "толпа" (700+ ежедневных уникальных посетителей), то данная задача вполне может быть реализована.

--
Как думаете, идея стоит свеч Подмигивание ?
6. Мелкий - 27 Июня, 2011 - 10:22:34 - перейти к сообщению
LEONeso, лучшее решение, что я видел:
0) у записи сохраняем дату последнего редактирования
1) при открытии записи на редактирование, сохраняем в сессию/невидимое поле дату последнего редактирования
2) при сохранении данных проверяем текущую дату в базе и сохранённую у нас. Если они различаются - выводим пользователю что-то вроде "запись уже редактировалась, возможно вы захотите изменить что-то ещё", то, что написал он, то, что сохранено в базе.
2,5) для удобства пользователя, можно аяксом тыкать нужную запись на предмет её обновления и в случае такового, вывести пользователю всё то же сообщение.

Так мы сразу облегчаем и проблемы с блокировками и проблемы с перезаписью данных человеком, который отошёл на эти 5 минут.
7. LEONeso - 27 Июня, 2011 - 10:37:05 - перейти к сообщению
Мелкий, мне немного не понятная работа сессий, сессия создается на стороне сервера и записывается ключ в кукисах, если куки у пользователя отключены, сверка сессии будет невозможна? и от сюда может случится параллейное редактирование (кто последний тот и сохранит данные).

Если же сессия работает, только на стороне сервера без куки, то как он может определить владельца сессии?

Пример: Когда я создаю запись в кукис, то использую следующий код

т.е. используя текущую дату я плюсу ровно год, после года, кука удаляется браузером.

Аналогичные действия я хочу сделать с записью даты окончания блокирования доступа к записи. Если пользователь закончит редактирование записью в бд (кнопка "сохранить"), то дата окончания блокировки будет удалена. Следующий запрос к этой записи выведет данные и обновит дату окончания блокировки записи. На всё даётся 5 минут.
8. Мелкий - 27 Июня, 2011 - 11:32:19 - перейти к сообщению
LEONeso пишет:
если куки у пользователя отключены, сверка сессии будет невозможна?

Если куки отключены (и данная настройка не отключена в php.ini, не помню её точного названия) - то id сессии будет передаваться GET'ом.
Ну и а так же дату можно сохранить в input type='hidden'.

А если привязывать к 5 минутам времени - то это будет называться "короткоживущий токен". Способы его создания:
0) get-параметр
1) кука
2) сессия
3) можно и в форму скрытое поле ставить
4) или их комбинация
9. LEONeso - 27 Июня, 2011 - 12:12:39 - перейти к сообщению
Мелкий, я обдумал каждый, предложенный Вами, альтернативный вариант.

GET/POST не подойдет - это статические данные, которые создаются при заходе на страницу, в данном случае дата будет всё время одинакова пока человек находится на странице (на странице могут быть более 100 изображений, при нажатии на которых, передаётся get запрос в фрейм, который в свою очередь безопасно обрабатывает запрос и выдаёт необходимые данные, приоритет проверки - это первоначальная чистка от кода и проверка существования файла, если его не существует, то речь не может идти о работе с БД).

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

Сессия подходит - вполне разумное решение данной задачи, но всё упирается в настройки браузера пользователя.

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

Хочу напомнить, что цель исключить параллельное редактирование записи, кука на стороне клиента, сессия на обоих сторонах, база данных на стороне сервера... не разумно давать каждой странице проверять целую базу, чтобы динамически отслеживать возможность редактирования той или иной записи в БД. Таким образом, мне кажется (я почти уверен в этом), что запись окончания блокировки "записи БД" будет разумной, но и тут есть подводный камень - это отправка 2-х запросов при обработке полученных GET:
1 - запрос, чистки и после проверок существования файла, который выведет ассоциативный массив mysql_fetch_ASSOC и код, после проверки даты окончания блокировки, начнет выводить разметку с данными.

2 - запрос, update даты окончания блокировки записи) таким образом, мы фактически исключаем возможность параллельного редактирования записи т.к. кто переев обработает 2-й запрос, тот и получит доступ к редактированию и 5 минут блокировки записи, если человек сохранит данные, то блокировка спадает иначе по истечению времени при первом запросе, будет проверена дата, если запить блокирована, то 2-го запроса не будет, выведет текст о просьбе "подождать и попробовать снова".

Вроде бы, обмануть невозможно... дата используется серверная, от куда бы не пришел человек, дата+время всегда будет актуальной.
10. DeepVarvar - 27 Июня, 2011 - 12:18:48 - перейти к сообщению
DeepVarvar пишет:
нажмет в браузере history.go(-1), передумает сохранять результат
DeepVarvar пишет:
А это ты не угадаешь какое время поставить 5 мин? 20мин? 60???

ПЕРВЫЙ юзер справился за 1 мин,
ВТОРОЙ отправив через пол часа данные на сохранение - будет весьма удивлен т.к.
ТРЕТИЙ юзер сейчас залочил доступ для всех кроме себя.
11. Мелкий - 27 Июня, 2011 - 12:41:39 - перейти к сообщению
LEONeso пишет:
Сессия подходит - вполне разумное решение данной задачи, но всё упирается в настройки браузера пользователя.

Почему? При чём тут настройки браузера?

LEONeso пишет:
GET/POST не подойдет - это статические данные, которые создаются при заходе на страницу, в данном случае дата будет всё время одинакова пока человек находится на странице (на странице могут быть более 100 изображений, при нажатии на которых, передаётся get запрос в фрейм, который в свою очередь безопасно обрабатывает запрос и выдаёт необходимые данные, приоритет проверки - это первоначальная чистка от кода и проверка существования файла, если его не существует, то речь не может идти о работе с БД).

Так токен выдавать непосредственно при генерировании фрейма, зачем он всей странице.

Мне не нравится сама идея блокирования, делал так уже, неудобно.
12. LEONeso - 27 Июня, 2011 - 14:17:31 - перейти к сообщению
Мелкий, я замечал, что при создании сессии создаётся и кука, иначе как сервер определить, что это тот же пользователь? ip (что если прокси)?

DeepVarvar, да - это получается уже параллельное редактирование где один из пользователь остаётся в пролёте... честно сказать, уже начал запутываться...

Как же тогда это реализовывается средствами php?
Ведь нужно учитывать начало и конец редактирования, если убрать лимит блокировки, то пока человек не сделает определённое действие (сохранить) блокировка не снимется (возможно установить дополнительный часовой лимит с фоновым счетчиком в заголовке, где через 60 минут, будет обновлена страница с get параметром на выдачу сообщения о том, что страница устарела и требуется её обновить нажатием по ссылке, которая уже передаст прежний get параметр или можно выбрать другой файл).

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

Возможно я уже начал усложнять процесс достижения Цели Растерялся ?
13. Мелкий - 27 Июня, 2011 - 14:35:46 - перейти к сообщению
LEONeso пишет:
я замечал, что при создании сессии создаётся и кука, иначе как сервер определить, что это тот же пользователь?

Да, кука. Но если пользователь не принимает куку - то устанавливается GET-параметр. Автоматически механизмом сессий.
14. LEONeso - 27 Июня, 2011 - 14:42:01 - перейти к сообщению
Мелкий, не могу понять смысл сессии, если не блокировать запись от редактирования другими пользователями?
15. Мелкий - 27 Июня, 2011 - 14:44:13 - перейти к сообщению
LEONeso пишет:
не могу понять смысл сессии, если не блокировать запись от редактирования другими пользователями?

Мелкий пишет:
2) при сохранении данных проверяем текущую дату в базе и сохранённую у нас. Если они различаются - выводим пользователю что-то вроде "запись уже редактировалась, возможно вы захотите изменить что-то ещё", то, что написал он, то, что сохранено в базе.

Да, мне вообще не нравится идея с блокировками. Делал так как-то, неудобно.

 

Powered by ExBB FM 1.0 RC1