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. Техническую сторону вопроса я сознательно опустил, поскольку в данном случае вопрос был не об этом. А описание особенностей работы отдельных команд слишком увело бы в сторону. ------------------ |
Re: Локальный View и Транзакция | |
---|---|
Syberex Сообщений: 1432 Откуда: Кострома Дата регистрации: 19.01.2004 |
В дополнение хотел вложить doc-файл, в нем глава "Shared Access" из ONLINE документации
к VFP5 - там есть картинки, будет проще понять про кальку ;) (правда на английском) Он в zip-е он вышел 129 кб, а тут ограничение в 30 кб... Что делать? ------------------ |
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% НЕВОЗМОЖНО. Цитата:См. п1 Цитата:Транзакция, будучи открытой, "забирает" в себя ВСЕ изменяемые внутри неё таблицы и представления - конечно если они в принципе поддерживаются (скажем FREE таблицы вплоть до VFP9 не могли участвовать в транзакциях). Управлять "это бери а то нет" - невозможно. Цитата:Это правильно - после того как ты сохранил данные, желательно перезапросить представление - чтоб подтянулись новые данные из связанных таблиц, чтоб учесть сработавшие для таблиц Default-ы, триггера, Rule-сы и т.п. Хотя конечно если всего этого нету, то перезапрос будет излишним - ибо ничего нового в представление он не внесёт. ------------------ WBR, Igor |
Re: Локальный View и Транзакция | |
---|---|
Каратаев Сообщений: 3974 Откуда: Алматы Дата регистрации: 04.12.2001 |
Спасибо! Лучшей АКАДЕМИИ чем наш VFP-клуб и не придумаешь!
Цитата:Ну не так все безнадежно. Ты уже как-то объяснял и коды приводил, так-что по поводу буферизации и транзакции ну хоть самому впору лекции читать В данном случае заморочка была в другом: Есть представление которое обновляет ТОЛЬКО ОДНУ таблицу и это представление имеет 5 или 3 буферизацию (в данном контексте - это не суть важно). В DE формы лежит эта таблица, допустим не буферизированная... Теперь, вношу изменения в View - в какой момент происходит фактическое изменение таблицы? Т.е. влияет ли TABLEUPDATE() для View и на таблицу тоже? Вот здесь были мои сомнения, поэтому я и ставил буферизацию на таблице и запускал транзакцию для сброса изменений. Цитата:Да... вот и мое незнание Цитата:Владимир сформулировал мою проблему лучше чем я сам Цитата:У меня TABLEUPDATE() внутри транзакции. А иначе смысл? В моем случае буферизация таблицы видимо была излишней, но в некоторых ситуациях, как я понял, это необходимо. Хотя, с другой стороны сказать, что вариант, когда я ставлю буферизацию на все неверный - тоже нельзя. Избыточен - да! Не всегда нужен - да! Короче говоря мне надо более вдумчиво подходить к каждому конкретному случаю, а не пытаться использовать стандартные схемы... Спасибо! ------------------ Никогда не бывает настолько плохо, чтобы не могло быть еще хуже. |
Re: Локальный View и Транзакция | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Hi, Каратаев!
Цитата:Смотря что ты считаешь за "фактическое изменение"! Если физическую запись на диск - то см. пару топиками выше. Если логическую запись в рамках ОС (так чтобы все прочие программы видели внесённые изменения, если они будут считывать таблицу - то тут влияет расположение звёзд на небе, но обычно очень быстро после того как фокс сделает запись в свои внутренние буфера - по идее FLUSH этому способствует, но реально вплоть до VFP9 ничего эта команда не делала). Если же сброс данных в собственно табличный кэш фокса (откуда данные видны всем другим курсорам, открываемых внутри данного процесса - т.е. для других форм, процедур и т.п.) - то это происходит непосредственно в момент исполнения Tableupdate - если буферизация есть только в представлении - то в представлении, если и в представлении и в таблице - то в момент Tableupdate таблицы. Цитата:Нет конечно. Считай что за Tableupdate стоит банальная команда UPDATE MyBaseTable SET ... (ну или соответственно Insert или DELETE) - т.е. данные "перекачиваются" из буфера представления в буфер таблицы - конечно если таблица НЕ буферизованна, то это равноценно перекачиванию данных в кэш (т.е. в образ dbf в памяти фокса, откуда уже сам фокс выпихивает их дальше - в кэш винды, и наконец оттуда на диск (тоже имеющий свой кэш кстати говоря) ). Цитата:Если ты СПЕЦИАЛЬНО хочешь чтобы данные проходили через 2 сита, то конечно так и нужно делать, но обычно этого не требуется. Цитата:TableUpdate равно как и буферизация вообще не связана никак с транзакцией - это 2 совершенно независимых процесса. И внутренне они работают по разному! Потому можно (и нужно) использовать Tableupdate вне зависимости от наличия транзакции - равно как и наоборот - можно использовать транзакцию БЕЗ использования буферизации. Цитата:Видимо да. Цитата:Совершенно верно. Что не запрещено, то разрешено Скажем так - скорее всего нецелесообразный, но вполне допустимый. ------------------ WBR, Igor |
Re: Локальный View и Транзакция | |
---|---|
bell Сообщений: 167 Откуда: Харьков Дата регистрации: 04.04.2002 |
2 Syberex - Не очень понятна фраза:
Цитата:Данные действительно блокируются, но ведь после END TRANSACTION они опять всем доступны. Если транзакции делать быстро, т.е. отделить этап "Внесение изменений"от этапа "Сохранение внесенных изменений" (по Владимиру Максимову), то все будет ОК. |
Re: Локальный View и Транзакция | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Hi, bell!
Цитата:Для того и писалось, чтобы все понимали что транзакции надо делать быстро Точнее что в процессе транзакции нельзя создавать состояний ожидания (MESSAGEBOX например не говоря уж о форме ввода)... ------------------ WBR, Igor |
Re: Локальный View и Транзакция | |
---|---|
Каратаев Сообщений: 3974 Откуда: Алматы Дата регистрации: 04.12.2001 |
Igor Korolyov
Спасибо. Цитата:Вот это мне действительно непонятно А что тогда выполнять в такой транзакции? Видимо прав был Владимир Максимов - не понимаю я сути, оказывается... ------------------ Никогда не бывает настолько плохо, чтобы не могло быть еще хуже. |
Re: Локальный View и Транзакция | |
---|---|
Syberex Сообщений: 1432 Откуда: Кострома Дата регистрации: 19.01.2004 |
Цитата:Ответ: TABLEUPDATE() например... И если он завершится неудачно, нужно откатить , иначе фиг поймешь, что записалось, а что нет... А если несколько TABLEUPDATE-ов? Вот тут серьезно нужна транзакция... ------------------ |
Re: Локальный View и Транзакция | |
---|---|
Каратаев Сообщений: 3974 Откуда: Алматы Дата регистрации: 04.12.2001 |
Syberex
Цитата:Как раз таки мой вопрос был связан с тем, что Игорь написал "можно использовать транзакцию БЕЗ использования буферизации". Другими словами, как я понял, что в транзакции tableupdate() может и НЕ присутствовать. Поэтому и спросил - что же тогда в ней выполнять? ------------------ Никогда не бывает настолько плохо, чтобы не могло быть еще хуже. |
© 2000-2024 Fox Club  |