VAB> Здравствуйте, Олег.
VAB> Ответ на Ваше письмо от 22 сентября 2002 г., 22:38:50
VAB> Большое спасибо за Ваши ответ и мнение.
VAB> И если можно, один маленький вопрос.
VAB> Ранее Андрей Мялин мне уже советовал, правда для драйвера Pervasive
VAB> Btrieve, использовать пару LOGOUT()-COMMIT.
VAB> Теперь Вы советуете эту же пару для драйвера TPS.
VAB> Вопрос вот какой:
VAB> Каким образом применение транзакции влияет НА БУФЕРИЗАЦИЮ данных ?
VAB> Сознаюсь, что я ещс не пробовал этот метод для TPS, но обязательно
VAB> попробую.
VAB> И ещс один вопросик:
VAB> Ваши рекомендации по использованию пары STREAM()-FLUSH() относятся к
VAB> использованию пары LOGOUT()-COMMIT ?
VAB> Вы сами понимаете, что открытие-закрытие транзакции для каждого цикла
VAB> несколько замедлит обработку. Это я уже проходил и не один раз.
VAB> Или одну пару LOGOUT()-COMMIT применять для всех циклов обработки ?
Для драйвера «TopSpeed» (.TPS) транзакция, в отличии от драйвера «Clarion» (.DAT), не замедляет а УСКОРЯЕТ процесс обработки! И значительно! Раньше я как-то уже приводил сравнительные данные. В среднем, транзакция для TPS ускоряет процесс обработки (ADD/PUT/DELETE) ~5-10 раз. Бывает меньше, но бывает и больше!
Это связано с тем, что после включения режима транзакции (оператором LOGOUT) ВСЕ изменения файлов, включенных в рамки текущей транзакции, накапливаются в оперативной памяти рабочей станции, на которой включена эта транзакция. Естественно, что при включении транзакции файлы автоматически блокируются от изменений на других станциях.
Т.е., во время транзакции файлы физически НЕ модифицируются. После отмены транзакции (оператором ROLLBACK) происходит простое очищение памяти рабочей станции и разблокирование файлов. После успешного завершения транзакции (оператором COMMIT) производится реальная модификация файлов в пакетном режиме, что ЗНАЧИТЕЛЬНО быстрее, чем пооператорная модификация.
В связи с вышесказанным, можно сделать вывод, что рамки одной транзакции ограничены двумя параметрами:
- доступной оперативной памятью рабочей станции Что-бы не допустить свопинга, что значительно замедляет процесс и фактически сводит «на нет» все преимущество.
- временем, которое необходимо для пакетной моификации рабочих файлов после успешного закрытия транзакции Иногда может достигать до 20-40 минут(!), что «нервирует» пользователя (так-как этот процесс не поддается никакой визуализации — ощущение что машина просто «висит») и может привести к порче файлов БД с потерей части данных при воникновении в это время нештатных ситуаций (сбой сетевой карточки или кабеля, вырубание электроэнергии и пр.).
Поэтому я и рекомендую не «заворачивать» большие циклы в один фрагмент LOGOUT-COMMIT. Что-то типа:
MaxCounter EQUATE(1000) LOC:TranBreak BYTE LOC:Logout BYTE LOC:Counter LONG ... do OpenTran LOC:TranBreak = False Clear(LOC:Counter) Set(File) Loop Next(File); if ErrorCode() then Break. ! Модификация файла "File" if ErrorCode() LOC:TranBreak = True Break . LOC:Counter += 1 do ReTran . do CloseTran ... OpenTran Routine Logout(1,File) if ~ErrorCode() then LOC:Logout = True else LOC:Logout = False. CloseTran Routine if LOC:Logout if LOC:TranBreak then RollBack() else Commit(). LOC:Logout = False . ReTran Routine if (LOC:Counter % MaxCounter) = 0 do CloseTran do OpenTran .
В этом примере транзакционных буфер будет обновлятся каждые 1000 записей. Реальное значение константы MaxCounter лучше всего подбирать для каждой транзакции отдельно. В первую очередь оно зависит от общего размера буферов файлов, которые участвуют в рамках одной транзакции. Кол-во записей в этих файлах реально начинает влиять на это значение только при довольно больших кол-вах.
Да! И, естественно, в рамках транзакции нет надобности в использовании STREAM/FLUSH.