:: Архив конференции по VFP до 2005 года
Re: Локальный View и Транзакция
Владимир Максимов
Автор

Сообщений: 14095
Откуда: Москва
Дата регистрации: 02.09.2000
Обычно процесс модификации данных разбивается на несколько этапов:

-) Поиск того, что собираются изменять
-) Внесение изменений
-) Сохранение внесенных изменений

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

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

В FoxPro для создания такой промежуточной структурой введено понятие "буферизации".

Буфер похож на прозрачную кальку, наложенную на печатный лист. Вроде бы исправляешь непосредственно написанное, но сам исходный текст при этом не меняется. Достаточно убрать кальку с листа и исходный текст окажется каким был. А вот когда убедился, что все изменил правильно, то переносишь изменения с кальки на исходный текст.

А что же такое Local View? По сути - это копия этого самого листа. Не калька, наложенная поверх, а именно копия. Отдельный лист.

В FoxPro Local View можно сделать обновляемым. Это значит, что изменения внесенные во View могут быть сброшены в исходные таблицы, на основании которых, этот View был создан. Т.е. изменения внесенные в копию листа автоматически попадут в исходный лист.

Нас это никак не устраивает. Поскольку в этом случае процесс внесения изменений и процесс сохранения внесенных изменений становятся одним процессом. Необходимо разделить эти процессы. Т.е. подложить "кальку" (буфер). Весь вопрос в том, куда?

Либо между исходным листом и ее копией (буферизация исходной таблицы), либо поверх копии (буферизация View), либо сделать и то и другое (положить 2 кальки).

Частично, разработчики FoxPro уже решили эту дилему. Дело в том, что любое View в FoxPro всегда открывается в режиме оптимистической буферизации. Либо строк (3), либо таблиц (5). Т.е. поверх View и так всегда лежит эта калька. И снять ее нет никакой возможности. Нельзя отключить буферизацию View.

Значит вопрос стоит не в том, где именно должна лежать эта калька, а в том, надо ли к той кальке, которая лежит поверх View положить еще одну между View и исходной таблицей?

Вопрос не однозначный. Зависит от конкретной задачи.

Например, если в таблице используются автоинкрементные поля (Integer-autoincrement), то новое значение такого поля я никак не смогу получить пока не создам новую запись в исходной таблице. Т.е. буфер View в этом случае бесполезен. Я не могу написать в нем нужное мне значение поскольку просто его не знаю. А вот буфер исходной таблицы очень даже кстати. Вот в нем-то я и получу искомое значение.


Теперь рассмотрим вопрос сохранения внесенных изменений.

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

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


Для предотвращения подобной ситуации в FoxPro было введено специальное понятие "транзакция".

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

Т.е. в состояние до начала транзакции возвращаются не только таблицы и View, но и буферы, наложенные на эти таблицы. Можно смело повторять попытку сохранения с того места откуда начал. Заново накладывать эту глобальную кальку. Или сначала покорректировать локальные кальки отдельных таблиц или View.


Разумеется, это только общая схема. Не надо понимать сравнение с листами и прозрачной калькой слишком буквально. Это сравнение я привел для того, чтобы подчеркнуть некоторые особенности работы буферов и транзакции в FoxPro.

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




------------------
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
Syberex

Сообщений: 1432
Откуда: Кострома
Дата регистрации: 19.01.2004
В дополнение хотел вложить doc-файл, в нем глава "Shared Access" из ONLINE документации
к VFP5 - там есть картинки, будет проще понять про кальку ;) (правда на английском)
Он в zip-е он вышел 129 кб, а тут ограничение в 30 кб...
Что делать?




------------------
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Hi, Каратаев!

Уж полночь близится, а Германа всё нет Видимо Владимир, как и я,
предпочитает по ночам письма писать
Не знаю чего он распишет, потому так кратенько попробую:
1) "Надо ли буферизовать Представление" - а ты ради интереса попробуй его НЕ
буферизовать Что не выходит то-то и оно - представление ВСЕГДА
буферизовано. Другой вопрос какую из возможных буферизаций использовать -
строчную (3) или табличную (5) - я предпочитаю 5, как более управляемую -
ибо при 3-й может самостоятельно происходить сброс буфера - а мне такого
конечно не нужно.
2) "Выставил буферизацию и на таблицу(ы) и на View" - вот этого я понять не
могу. Зачем нужен ещё один уровень буферизации? Тебе не лень прописывать
TableUpdate и для View, и потом для самих таблиц?Мне - лень, потому сами
базовые таблицы я никогда не буферизую (ессно если реально работаю с
представлениями). В принципе можно найти 1-2 момента когда есть некоторая
польза от такой "двойной" буферизации, но это зависит исключительно от стиля
программирования - т.е. я например избегаю тех ситуаций когда это было-бы
оправдано - простота прежде всего
3) "Транзакция" - в ЭТОМ случае транзакция практически бессмысленна -
конечно если у тебя записи представления НЕ взаимосвязаны (такое бывает, но
ОЧЕНЬ редко). А оправдана она когда есть 2 и более связанных представления,
и для сохранения согласованности нужно сохранить либо ВСЁ, либо НИЧЕГО - в
этом и есть главное предназначение транзакции.
4) Я не знаю твою схему, но на всякий случай напомню - делать представление
которое обновляет БОЛЕЕ ЧЕМ ОДНУ таблицу - это сложно и потенциально опасно.
Т.е. брать то информацию можно хоть из 20 таблиц (смотря сколько SQL
позволяет конечно) - а вот обновлять из представления - стоит лишь одну
таблицу.
5) Про твой "вариант" скажу так - это на 66% НЕВОЗМОЖНО.
Цитата:
- не ставить буферизацию для View;
См. п1
Цитата:
- запускать транзакцию только для таблиц;
Транзакция, будучи открытой, "забирает" в себя ВСЕ изменяемые внутри неё
таблицы и представления - конечно если они в принципе поддерживаются (скажем
FREE таблицы вплоть до VFP9 не могли участвовать в транзакциях). Управлять
"это бери а то нет" - невозможно.
Цитата:
- после чего requery для View.
Это правильно - после того как ты сохранил данные, желательно перезапросить
представление - чтоб подтянулись новые данные из связанных таблиц, чтоб
учесть сработавшие для таблиц Default-ы, триггера, Rule-сы и т.п. Хотя
конечно если всего этого нету, то перезапрос будет излишним - ибо ничего
нового в представление он не внесёт.




------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
Каратаев

Сообщений: 3974
Откуда: Алматы
Дата регистрации: 04.12.2001
Спасибо! Лучшей АКАДЕМИИ чем наш VFP-клуб и не придумаешь!
Цитата:
Но, видимо, ты опять не понимаешь, для чего именно нужна буферизация, View и транзакция.
Ну не так все безнадежно. Ты уже как-то объяснял и коды приводил, так-что по поводу буферизации и транзакции ну хоть самому впору лекции читать
В данном случае заморочка была в другом:
Есть представление которое обновляет ТОЛЬКО ОДНУ таблицу
и это представление имеет 5 или 3 буферизацию (в данном контексте - это не суть важно).
В DE формы лежит эта таблица, допустим не буферизированная...
Теперь, вношу изменения в View - в какой момент происходит фактическое изменение таблицы?
Т.е. влияет ли TABLEUPDATE() для View и на таблицу тоже?
Вот здесь были мои сомнения, поэтому я и ставил буферизацию на таблице и запускал транзакцию для сброса изменений.
Цитата:
Про твой "вариант" скажу так - это на 66% НЕВОЗМОЖНО.
Цитата:
- не ставить буферизацию для View;
См. п1
Да... вот и мое незнание
Цитата:
Значит вопрос стоит не в том, где именно должна лежать эта калька, а в том, надо ли к той кальке, которая лежит поверх View положить еще одну между View и исходной таблицей?
Вопрос не однозначный. Зависит от конкретной задачи.
Владимир сформулировал мою проблему лучше чем я сам
Цитата:
Если запускаешь транзакцию перед тем как делать Tableupdate(),
а после (если все правильно сохранено) закрываешь транзакцию, то все верно. (тоже так делаю )
У меня TABLEUPDATE() внутри транзакции. А иначе смысл?
В моем случае буферизация таблицы видимо была излишней, но в некоторых ситуациях, как я понял, это необходимо.
Хотя, с другой стороны сказать, что вариант, когда я ставлю буферизацию на все неверный - тоже нельзя. Избыточен - да!
Не всегда нужен - да!
Короче говоря мне надо более вдумчиво подходить к каждому конкретному случаю, а не пытаться использовать стандартные схемы...
Спасибо!




------------------
Никогда не бывает настолько плохо, чтобы не могло быть еще хуже.
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Hi, Каратаев!

Цитата:
Теперь, вношу изменения в View - в какой момент происходит
фактическое изменение таблицы?
Смотря что ты считаешь за "фактическое изменение"! Если физическую запись на
диск - то см. пару топиками выше. Если логическую запись в рамках ОС (так
чтобы все прочие программы видели внесённые изменения, если они будут
считывать таблицу - то тут влияет расположение звёзд на небе, но обычно
очень быстро после того как фокс сделает запись в свои внутренние буфера -
по идее FLUSH этому способствует, но реально вплоть до VFP9 ничего эта
команда не делала). Если же сброс данных в собственно табличный кэш фокса
(откуда данные видны всем другим курсорам, открываемых внутри данного
процесса - т.е. для других форм, процедур и т.п.) - то это происходит
непосредственно в момент исполнения Tableupdate - если буферизация есть
только в представлении - то в представлении, если и в представлении и в
таблице - то в момент Tableupdate таблицы.
Цитата:
Т.е. влияет ли TABLEUPDATE() для View и на таблицу тоже?
Нет
конечно.
Считай что за Tableupdate стоит банальная команда UPDATE MyBaseTable SET ...
(ну или соответственно Insert или DELETE) - т.е. данные "перекачиваются" из
буфера представления в буфер таблицы - конечно если таблица НЕ
буферизованна, то это равноценно перекачиванию данных в кэш (т.е. в образ
dbf в памяти фокса, откуда уже сам фокс выпихивает их дальше - в кэш винды,
и наконец оттуда на диск (тоже имеющий свой кэш кстати говоря) ).
Цитата:
Вот здесь были мои сомнения, поэтому я и ставил буферизацию на
таблице и запускал транзакцию для сброса изменений.
Если ты СПЕЦИАЛЬНО хочешь чтобы данные проходили через 2 сита, то конечно
так и нужно делать, но обычно этого не требуется.
Цитата:
У меня TABLEUPDATE() внутри транзакции. А иначе смысл?
TableUpdate равно как и буферизация вообще не связана никак с
транзакцией - это 2 совершенно независимых процесса. И внутренне они
работают по разному!
Потому можно (и нужно) использовать Tableupdate вне зависимости от наличия
транзакции - равно как и наоборот - можно использовать транзакцию БЕЗ
использования буферизации.
Цитата:
В моем случае буферизация таблицы видимо была излишней
Видимо да.
Цитата:
Хотя, с другой стороны сказать, что вариант, когда я ставлю
буферизацию на все неверный - тоже нельзя
Совершенно верно. Что не запрещено, то разрешено Скажем так - скорее
всего нецелесообразный, но вполне допустимый.




------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
bell

Сообщений: 167
Откуда: Харьков
Дата регистрации: 04.04.2002
2 Syberex - Не очень понятна фраза:
Цитата:
При работе с транзакциями остается одно НО - данные (измененные) при транзакции блокируются,
следовательно недоступны больше никому в сети , можно запустить 2 Фокса,
сделать Browse для одной и тойже таблицы в первом делаем BEGIN TRANSACTION изменяем
пару записей и пробуем их во втором - все ясно...
Данные действительно блокируются, но ведь после END TRANSACTION они опять всем доступны. Если транзакции делать быстро, т.е. отделить этап "Внесение изменений"от этапа "Сохранение внесенных изменений" (по Владимиру Максимову), то все будет ОК.
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Hi, bell!

Цитата:
Если транзакции делать быстро
Для того и писалось, чтобы все понимали что транзакции надо делать быстро
Точнее что в процессе транзакции нельзя создавать состояний ожидания
(MESSAGEBOX например не говоря уж о форме ввода)...




------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
Каратаев

Сообщений: 3974
Откуда: Алматы
Дата регистрации: 04.12.2001
Igor Korolyov
Спасибо.
Цитата:
можно использовать транзакцию БЕЗ использования буферизации.
Вот это мне действительно непонятно
А что тогда выполнять в такой транзакции? Видимо прав был Владимир Максимов - не понимаю я сути, оказывается...




------------------
Никогда не бывает настолько плохо, чтобы не могло быть еще хуже.
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
Syberex

Сообщений: 1432
Откуда: Кострома
Дата регистрации: 19.01.2004
Цитата:
А что тогда выполнять в такой транзакции?
Ответ: TABLEUPDATE() например...
И если он завершится неудачно, нужно откатить ,
иначе фиг поймешь, что записалось, а что нет...
А если несколько TABLEUPDATE-ов? Вот тут серьезно нужна транзакция...




------------------
Ratings: 0 negative/0 positive
Re: Локальный View и Транзакция
Каратаев

Сообщений: 3974
Откуда: Алматы
Дата регистрации: 04.12.2001
Syberex
Цитата:
Ответ: TABLEUPDATE() например...
Как раз таки мой вопрос был связан с тем, что Игорь написал "можно использовать транзакцию БЕЗ использования буферизации". Другими словами, как я понял, что в транзакции tableupdate() может и НЕ присутствовать. Поэтому и спросил - что же тогда в ней выполнять?




------------------
Никогда не бывает настолько плохо, чтобы не могло быть еще хуже.
Ratings: 0 negative/0 positive


Извините, но у вас нет прав для того, чтобы оставлять сообщения в этом форуме.

On-line: 5 (Гостей: 5)

© 2000-2024 Fox Club 
Яндекс.Метрика