Форум » LetoDB, HbNetio. » Архивация в letodb » Ответить

Архивация в letodb

Pasha: Хочу посоветоваться. Задача - сделать бэкап (архив) базы в произвольный момент времени. Пусть архиватор будет 7z, хотя это не принципиально. Утилита запускается на сервере, где установлен letodb, по определенному графику (хотя бы планировщиком). Входные параметры: каталог БД и список расширений файлов, которые надо поместить в архив. Предлагается такой алгоритм: сканируется все содержимое каталога БД, и формируется список @listfiles для архиватора. Если это не файл данных, он просто добавляется в список. Если это файл данных, то выполняется попытка его открыть монопольно. Если попытка успешная - файл закрывается и добавляется в список. Если нет - добавляется в список № 2 для 2-го прохода. Для 1-го прохода через run вызывается архиватор, и ему дается список файлов. Для 2-го прохода создается новый каталог, куда средствами letodb через команду copy to копируются открытые файлы, затем вызывается архиватор с командой добавления в архив файлов, которые не были заархивированы во время 1-го прохода. Какие будут идеи ?

Ответов - 127, стр: 1 2 3 4 5 6 7 All

PSP: А зачем два прохода? По расписанию COPY TO во временную папку и потом архивировать.

Pasha: Чтобы не копировать те файлы, которые не открыты letodb Копирование больших файлов может быть длительной операцией, и в этом случае в ней нет необходимости

Петр: Pasha пишет: Если это не файл данных, он просто добавляется в список. Если это файл данных, то выполняется попытка его открыть монопольно. Если попытка успешная - файл закрывается и добавляется в список. Если нет - добавляется в список № 2 для 2-го прохода. Для 1-го прохода через run вызывается архиватор, и ему дается список файлов. А между первым и вторым проходом ничего не произойдет? Что-то откроется, что-то закроется?


petr707: Цитата: Пусть архиватор будет 7z, хотя это не принципиально. Утилита командной строки 7za допускает ключ архивации открытых в Shared файлов. Так что, может и "принципиально" ? Тогда не нужен проход 2 ?

Pasha: petr707 пишет: Утилита командной строки 7za допускает ключ архивации открытых в Shared файлов. Это не поможет, так как letodb открывает файлы монопольно.

Pasha: Петр пишет: А между первым и вторым проходом ничего не произойдет? Что-то откроется, что-то закроется? Конечно, это узкое место. Поэтому и прошу совета. Может быть, кто-то предложит делать по-другому.

PSP: Может прикрутить отдельный поток к серверу, который будет запускать при наличии определенного ключа в ini-файле и параллельно копировать все изменения во всех файлах, которые делает сервер? Будет самая актуальная копия.

AlexMyr: PSP пишет: параллельно копировать все изменения во всех файлах, которые делает сервер? Будет самая актуальная копия. это уже какой-то raid-массив получится Pasha пишет: Для 2-го прохода создается новый каталог, куда средствами letodb через команду copy to копируются открытые файлы, затем вызывается архиватор с командой добавления в архив файлов, которые не были заархивированы во время 1-го прохода. А если во время 2-го прохода база осталась (или открыли) в монопольном режиме, что тогда делать?

PSP: AlexMyr пишет: это уже какой-то raid-массив получится Ну, необязательно "на лету" это делать. Скажем, сервер ведет лог операций с записями, который обрабатывается по определенному расписанию отдельным потоком.

AlexMyr: PSP пишет: Скажем, сервер ведет лог операций с записями, который обрабатывается по определенному расписанию отдельным потоком. Но задача Pasha пишет: сделать бэкап (архив) базы в произвольный момент времени.

PSP: Расписание в ini-файле мало чем отличается от произвольного момента. К примеру, ввести в ini-файл параметр BackupEvery = <кол-во минут>. Но... это - мечты... Решение за Пашей. PS. Сделать "стандартный" бэкап в "произвольный момент времени" не представляется возможным по той причине, что файлы открыты другим приложением (сервером) в монопольном режиме. Придётся ждать освобождения, а потом обеспечить копирование данных, не мешая серверу, т.к. он в любой момент после начала бэкапа может потребовать "отдать файлы" назад. А у нас тут бэкап полным ходом... Даже, если открыть файлы в разделенном режиме, будет некорректно копировать данные из файлов, которые могут в любой момент измениться. Копия может быть, мягко говоря, неработоспособной. Я же предлагаю, чтобы при наличии определенного ключа в ini-файле сервер вёл лог изменений записей всех файлов в каком-то формате, отдельный поток читал бы этот лог и повторял все "манипуляции" сервера, но уже в совершенно других файлах. Этому же потоку можно поручить запуск внешнего архиватора, если нужно. Но, повторю, решение за Пашей...

Pasha: По поводу копирования всех изменений - проще использовать зеркалирование средствами ОС. Но только для архивации включать зеркалирование не хотелось бы. А по поводу 2-го прохода. Это letodb открывает файл монопольно. Но предполагается, что клиенты окрывают файлы в режиме разделения через letodb. И утилита архивирования может открыть их через letodb в режиме разделения. Перед copy to можно выдать fillock, другие клиенты при копировании гарантированно файл не изменят. А после копирования файл конечно будет закрыт, и архиватор будет иметь дело уже с созданной копией. Узкое место: во время 1-го прохода при работе архиватора letodb не сможет открыть файл, открытый архиватором. Или успеет открыть файл до того, как его откроет архиватор. Во время 2-го прохода может не сработает fillock. Но тут останется только ждать по таймауту. Еще вариант: можно, возложить архивацию на сам letodb, используя библиотеку работы с zip. В этом случае можно архивировать и открытые файлы, по файловому хэндлу. Но при этом сервер будет загружен несвойственными ему функциями, что мне не очень нравится.

Dima: Интересно а куда исчез alkresin Саша Кресин ?

AlexMyr: Pasha пишет: Еще вариант: можно, возложить архивацию на сам letodb, используя библиотеку работы с zip. В этом случае можно архивировать и открытые файлы, по файловому хэндлу. Но при этом сервер будет загружен несвойственными ему функциями, что мне не очень нравится. Как по мне, то это будет более приемлемый и рабочий вариант, т.к. архивирование происходит по требованию или допустим раз в сутки, а если понадобится раз в десять минут на протяжении двух часов, то вынужденная мера заставит и сервер нагрузить, и на звонки не отвечать, и потерпеть. И организовано будет все своими средствами, без привлечения сторонних программ.

AlexMyr: Dima пишет: Интересно а куда исчез alkresin Саша Кресин ? Тоже интересно, в том году пробовал писать ему - молчит.

Dima: AlexMyr пишет: Тоже интересно, в том году пробовал писать ему - молчит. Он всегда очень живо реагировал на любые изменения в LetoDB и тут бац и пропал. Надеюсь с ним все хорошо !?!!

Sergey Spirin: Pasha пишет: Еще вариант: можно, возложить архивацию на сам letodb, используя библиотеку работы с zip. В этом случае можно архивировать и открытые файлы, по файловому хэндлу. Но при этом сервер будет загружен несвойственными ему функциями, что мне не очень нравится. Ну, вообще, изготовление бэкапа вполне традиционное занятие для db-серверов. А как сейчас обстоят дела в лето с транзакциями? Есть ли snapshot-транзакции? Если нет, то по любому сервер останавливать, иначе целостного бэкапа не сделать вроде...

Pasha: snapshot-транзакции не поддерживаются, есть только read commited

Sergey Spirin: Pasha пишет: snapshot-транзакции не поддерживаются, есть только read commited Тогда очевидно, что сервер надо стопить. При этом ещё либо дождаться завершения всех активных транзакций, либо все их насильно откатить, не допуская, естественно, старта новых. В противном случае получим нарушение целостности данных. Бэкап не увидит данные некой транзакции X, при проходе одной таблицы, а при проходе другой таблицы транзакция X уже закоммитится и ее данные попадут в бэкап частично.

santy: Бэкап (архив) базы - это критическая операция, её желательно делать, когда пользователи не работают в базе . Возможны варианты: копирование не файлов, а записей которые были изменены во время работы до операции копирования.

Dima: santy пишет: Бэкап (архив) базы - это критическая операция, её желательно делать, когда пользователи не работают в базе У меня такое бывает крайне редко. Обычно это праздники. Обычно с базой идет работа 24 часа в сутки.

santy: Если база крутится постоянно, тогда нужно использовать средства сервера или специальные программы, например Effector saver 3 -Автоматическое архивирование баз данных 1С:Предприятия, произвольных данных .... Возможно ли в Letodb реализовать команды резервного копирования?

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

Sergey Spirin: Dima пишет: santy пишет:  цитата: Бэкап (архив) базы - это критическая операция, её желательно делать, когда пользователи не работают в базе У меня такое бывает крайне редко. Обычно это праздники. Обычно с базой идет работа 24 часа в сутки. Ну, если выбор "между двух зол", то пауза в работе сервера зло все-таки меньшее, чем неполноценный бэкап Паш, а на каких механизмах реализована поддержка транзакций в лето? Как обеспечивается одномоментность видимости всей совокупности изменений одной транзакции относительно других?

PSP: Pasha пишет: проще использовать зеркалирование средствами ОС Какими?

Pasha: PSP пишет: цитата: проще использовать зеркалирование средствами ОС Какими? Да вот хотя бы так: http://support.microsoft.com/kb/307880

PSP: Паш, там вот такой текст: [pre2]"Вы не можете создавать зеркальные тома на компьютерах под управлением Windows XP Home Edition, Windows XP Professional или Windows XP 64-Bit Edition. Однако вы можете использовать компьютер с Windows XP Professional для создания зеркальных томов на удаленных компьютерах, работающих под управлением серверных операционных систем Windows 2000 Server, Windows 2000 Advanced Server или Windows 2000 Datacenter Server."[/pre2] Только на Windows Server такое возможно. У меня же (да и у тебя, наверное) LetoDB работает на XP. А у некоторых - под Linux. Может все-таки присмотришься к моему предложению, а? Всё может делаться самим сервером, отдельным его потоком, ничего останавливать не надо, нагрузки большой, имхо, не будет, файлы (как основные, так и копия) всегда открыты монопольно, индексы для копии создавать не нужно.

AlexMyr: У меня на 98 крутится . PSP пишет: файлы (как основные, так и копия) всегда открыты монопольно, индексы для копии создавать не нужно. Я уже писал о своей проблеме, когда портится индекс и база с поврежденным заголовком, решаю ее удалением индекса и правкой базы с помощью dbedit (спасибо Паше ) - это происходит по причине пропадания питания (упс не предлагать ). Так вот, что будет с бекапом в такой ситуации и можно ли будет использовать его для восстановления для дальнейшей работы? И еще вопрос - как при PSP пишет: файлы (как основные, так и копия) всегда открыты монопольно, индексы для копии создавать не нужно. записать этот бекап на болванку, на флешку когда они открыты монопольно, север останавливать?

PSP: AlexMyr пишет: когда портится индекс и база с поврежденным заголовком, решаю ее удалением индекса и правкой базы с помощью dbedit (спасибо Паше ) - это происходит по причине пропадания питания (упс не предлагать ). Так вот, что будет с бекапом в такой ситуации и можно ли будет использовать его для восстановления для дальнейшей работы? Ну, сервер должен быть защищен бесперебойником в любом случае. А без него любой бэкап будет непригоден для использования. Даже полный бэкап от MS SQL Server, если во время его создания выключить питание. Я думаю, всё будет зависит от того, писались ли данные в бэкап в момент отключения или нет. Если не писались, то может быть он и будет исправен. Предсказать это невозможно, имхо. AlexMyr пишет: записать этот бекап на болванку, на флешку когда они открыты монопольно, север останавливать? Я уже писал, что потоку, который создает бэкап, можно также поручить периодическое архивирование в zip. А zip уже будет доступен для копирования и т.д.

AlexMyr: PSP пишет: Я уже писал, что потоку, который создает бэкап, можно также поручить периодическое архивирование в zip. А zip уже будет доступен для копирования и т.д. Так, допустим zip у нас с датой 18.01.2012 10:00, следующий будет создан через 12 часов (или через сколько?), сейчас допустим 18.01.2012 12:13 и мне надо проверить данные в архиве, как быть?

PSP: AlexMyr пишет: как быть? Можно придумать команду для сервера "Создать Архив Немедленно".

AlexMyr: PSP пишет: Можно придумать команду для сервера "Создать Архив Немедленно". Пришли к тому, о чем Паша спрашивал, вот

PSP: AlexMyr пишет: Пришли к тому, что Паша спрашивал, вот Нееее, отличия есть. Когда есть в наличии точная копия файлов базы данных, нет никакой проблемы сделать из нее zip. Даже zip делать не надо. Есть точная копия. PS. Но, всё зависит от Паши. Помочь ему в написании этого не могу, поэтому умолкаю.

Chikanuk: Pasha пишет: Пусть архиватор будет 7z 7z умеет такое: -ssw (Compress files open for writing) switch Compresses files open for writing by another applications. If this switch is not set, 7-zip doesn't include such files to archive. И делать update ( -u ). Хоть после каждой записи в таблицу...

AlexMyr: Chikanuk пишет: 7z умеет такое: Проверил: C:\TEMP\>7z a -ssw rrr.7z res.dbf 7-Zip 9.22 beta Copyright (c) 1999-2011 Igor Pavlov 2011-04-18 Scanning Updating archive rrr.7z Compressing res.dbf WARNING: Процесс не может получить доступ к файлу, так как этот файл занят други м процессом. WARNINGS for files: res.dbf : Процесс не может получить доступ к файлу, так как этот файл занят друг им процессом. ---------------- WARNING: Cannot open 1 file

PSP: Chikanuk, это для файлов, открытых в для совместного доступа. Для монопольно открытых не подойдет.

Sergey Spirin: PSP пишет: Может все-таки присмотришься к моему предложению, а? Всё может делаться самим сервером, отдельным его потоком, ничего останавливать не надо, нагрузки большой, имхо, не будет, файлы (как основные, так и копия) всегда открыты монопольно, индексы для копии создавать не нужно. А сформулируй точно своё предложение, я что-то его не понимаю.

PSP: Sergey Spirin пишет: А сформулируй точно своё предложение Попробую (всё это очень сыро, разумеется)... 1. Сервер при любой операции (добавление, удаление, изменение) с записями отражает факт операции в отдельном логе, где указывается тип операции, идентификатор файла, номер записи и значение изменяемых полей, если нужно. 2. Существуют файлы-копии в отдельной папке, в которые посредством отдельного потока того же сервера записываются последовательно те же изменения, которые внесены в лог. В каждой операции указан номер записи основного файла, изменения которой нужно сохранить. Переход в файлах-копиях осуществляется по номерам записей, т.е. достаточно быстро и отпадает необходимость в индексах. Алгоритм обработки лога нужно продумывать, чтобы он не раздувался безмерно. Обработка лога происходит либо с определенным интервалом, либо "на лету" (тоже нужно продумывать пробовать, чтобы не увеличивать сильно нагрузку). 3. Тот же поток, который делает копирование, может, при необходимости, запускать внешний архиватор для создания архива. Вот, вкратце. Можете пинать...

AlexMyr: 1-й поток - идет транзакция, все успешно, 2-й поток заметил изменения и начинает архивирование и одновременно в 1-ом потоке начинается новая транзакция при которой происходит сбой вплоть до падения letodb, в результате архив получился не полным или битым. Что делать? PSP пишет: Существуют файлы-копии в отдельной папке, в которые посредством отдельного потока того же сервера записываются последовательно те же изменения, которые внесены в лог. Я правильно понимаю, что поток который делает архивирование ждет когда закончится основная транзакция?

PSP: В лог должна попадать информация только о завершенных транзакциях. Только эти изменения должны копироваться. На самом деле вариантов сбоя очень много. Нужно продумывать. PS. Тут еще нужно понимать, какой необходимый уровень безопасности данных нужен. Не стОит доводить до паранойи.

Sergey Spirin: PSP пишет: Вот, вкратце. Можете пинать... Ну, почему пинать Но это все "техника", "способы реализации". С помощью каких механизмов что-то реализовать, тут Паше виднее. Вопрос тогда с другой стороны, а к чему этой техникой идем? "Какой бэкап" идеален с нашей общей точки зрения? Когда есть чётко сформулированная цель тогда и средства подбирать удобнее :)

Sergey Spirin: Аппаратный сбой приведет к порче бэкапа любого сервера, не думаю, что нужно принимать такую вероятность во внимание.

PSP: Sergey Spirin пишет: "Какой бэкап" идеален с нашей общей точки зрения? В общем-то да. Кому-то проще развернуть RAID-5 и 1 раз в сутки копировать файлы. Но, честно говоря, я бы не отказался от наличия в LetoDB функции бэкапа.

Sergey Spirin: PSP пишет: Но, честно говоря, я бы не отказался от наличия в LetoDB функции бэкапа. Нет-нет, я о бэкапе, зеркалирование имеет все-таки несколько другой смысл. Можно ли принять за аксиому вот такое утверждение: "Полноценный бэкап - это моментальный снимок БД на момент старта процесса бэкапа. "Снимок" включает в себя все данные закомиченные к моменту старта и не включает данные более поздних транзакций". Частичное попадание данных одной транзакции в бэкап недопустимо. ?

AlexMyr: Sergey Spirin пишет: Можно ли принять за аксиому вот такое утверждение: Скорее да, чем нет.

PSP: Sergey Spirin пишет: Можно ли принять за аксиому вот такое утверждение Думаю, можно. По-крайней мере, это утверждение довольно чётко описывает цель. Но я не знаю, как такой снимок сделать в контексте LetoDB.

Sergey Spirin: AlexMyr пишет: Скорее да, чем нет. PSP пишет: Думаю, можно. Тогда, можно ли считать аксиомой второе утверждение: "Прерывание работы сервера во время работы процесса бэкапа недопустимо". Если это аксиома, то я думаю, очевидно, что никакое внешнее средство, типа 7z, нам здесь не помошник. Но реализация такой задачи фактически сводится к реализации snapshot-транзакций в сервере Лето. Snapshot-транзакции это и есть такие транзакции, которые видят только данные существовавшие на момент их старта, ну и свои, конечно. ReadCommited-транзакции видят все закоммиченные данные и свои любые... На каких механизмах это можно реализовать Паше, конечно, лучше знать. Но мне кажется логичным, что начать надо с анализа реализации ReadCommited-транзакций, для попытки понять можно ли "вписаться" в тот же механизм. Но про механизм Паша что-то не ответил... Если же это не аксиома, а реализация snapshot-а затруднительно, то задача сводится к реализации такой остановки сервера "по команде", а чем копировать данные становится уже не так важно. Давайте определяться, аксиома ли это?

AlexMyr: Sergey Spirin пишет: Тогда, можно ли считать аксиомой второе утверждение: "Прерывание работы сервера во время работы процесса бэкапа недопустимо". Что такое прерывание работы сервера? Если сам сервер создает бэкап без использования внешних средств, это есть прерывание работы, или все таки это нужная фича сервера? И в целом, что такое актуальный бэкап, насколько он актуален через два, три часа, 15 минут, когда данные вносятся сотнями за 10, 40 минут, за сутки? Про второе утверждение, не знаю, и да, и нет.

PSP: Sergey Spirin пишет: "Прерывание работы сервера во время работы процесса бэкапа недопустимо". Это - не аксиома. Ответ зависит от конкретной задачи. Где-то "допустимо", где-то "недопустимо". Я предлагаю все-таки дождаться Пашу.

Sergey Spirin: AlexMyr пишет: Что такое прерывание работы сервера? Если сам сервер создает бэкап без использования внешних средств, это есть прерывание работы, или все таки это нужная фича сервера? Ok. Действительно, надо уточнить. Давайте "прерывание работы сервера" определим как "существенную временную паузу в обслуживании клиентских подключений и откат незавершенных транзакций, существовавших на момент прерывания". AlexMyr пишет: И в целом, что такое актуальный бэкап, насколько он актуален через два, три часа, 15 минут, когда данные вносятся сотнями за 10, 40 минут, за сутки? Ну, исходя из первого утверждения, во временном отношении, бэкап абсолютно актуален только на момент своего старта Но, мне кажется, здесь и разница с зеркалкой кроется. Не всегда, данные нужны строго актуальные. Потребность откатится часто вызвана не физическим разрушением, а логическим. И прогер, и админ, да и юзер могут такого "наколбасить", что лучше откатиться

AlexMyr: Паша, какие мысли?

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

Sergey Spirin: PSP пишет: Но для такого варианта нужно реализовывать полноценный механизм транзакций. Конечно, нужен какой-то механизм. PSP пишет: Думаю, для LetoDB пока это не подходит. :) Тогда вариант с "прерыванием работы сервера" фактически единственный для реализации полноценного бэкапа... Кстати, а "родственник" ADS на dbf-ах бэкапит?

Dima: Sergey Spirin пишет: Кстати, а "родственник" ADS на dbf-ах бэкапит? Да вроде есть такой механизм начиная с версии 8 http://www.hotsoft.ru/ADS/ads_80.htm

Sergey Spirin: Dima пишет: Да вроде есть такой механизм начиная с версии 8 http://www.hotsoft.ru/ADS/ads_80.htm Да, даже вот цитата оттуда "с нами перекликается": :) All backups can be performed while the database is in use and will provide a logically correct “snapshot” of the database at the time the backup is started. То есть, принципиально это реализуемо и для dbf-ов....

PSP: Sergey Spirin пишет: То есть, принципиально это реализуемо и для dbf-ов.... Да, но бывают казусы... http://devzone.advantagedatabase.com/dz/content.aspx?Key=17&RefNo=091104-2224

Петр: Ну вы здесь и наваяли Откуда можно скачать последнюю версию Leto, посмотреть так сказать.. типа :pserver:anonymous@hwgui.cvs.sourceforge.net:/cvsroot/hwgui

PSP: Петр пишет: Ну вы здесь и наваяли cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb checkout -r rel-1-mt letodb

Sergey Spirin: PSP пишет: Да, но бывают казусы... http://devzone.advantagedatabase.com/dz/content.aspx?Key=17&RefNo=091104-2224 Ух ты, перешел из этого топика на другой по ссылке и обнаружил эту статью: http://devzone.advantagedatabase.com/dz/content.aspx?Key=17&RefNo=090521-2178 Где четко разъясняется, что ADS-ный бэкап работает на принципе нашего "прерывания работы сервера" Гм.. Текущие транзакции он не откатывает, а пытается ждать когда они закончатся. И если не дождется, то вываливается с ошибкой

Петр: PSP пишет: cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb checkout -r rel-1-mt letodb А что от поддержки xHarbour уже отказались полностью?

PSP: Петр пишет: А что от поддержки xHarbour уже отказались полностью? Я не знаю. Паша рулит.

Pasha: Петр пишет: А что от поддержки xHarbour уже отказались полностью? Сервер собрать можно только под Harbour, а клиент - и под xHarbour, и под Harbour

Pasha: PSP пишет: 1. Сервер при любой операции (добавление, удаление, изменение) с записями отражает факт операции в отдельном логе, где указывается тип операции, идентификатор файла, номер записи и значение изменяемых полей, если нужно. 2. Существуют файлы-копии в отдельной папке, в которые посредством отдельного потока того же сервера записываются последовательно те же изменения, которые внесены в лог. В каждой операции указан номер записи основного файла, изменения которой нужно сохранить. Переход в файлах-копиях осуществляется по номерам записей, т.е. достаточно быстро и отпадает необходимость в индексах. Алгоритм обработки лога нужно продумывать, чтобы он не раздувался безмерно. Обработка лога происходит либо с определенным интервалом, либо "на лету" (тоже нужно продумывать пробовать, чтобы не увеличивать сильно нагрузку). 3. Тот же поток, который делает копирование, может, при необходимости, запускать внешний архиватор для создания архива. В этой схеме создание лога это явно лишнее звено. Сначала создавать лог при каждой операции, а затем его отдельно отрабатывать на зеркале. Тогда уж лучше при каждой операции update/append сразу отрабатывать ее на зеркале, в том же потоке, в котором обрабатывается основная операция, как триггер. Но такая схема будет слишком тяжеловесной. Сейчас я не вижу, как сделать бэкап без остановки сервера. А останавливать его не получится. Поэтому наверное прийдется делать отдельную утилиту, которая бы сначала создавала бы зеркало БД, а затем поддерживала бы это зеркало: обновляла бы изменившиеся таблицы. Ну а с зеркалом уже можно делать все что угодно.

AlexMyr: Pasha пишет: Поэтому наверное прийдется делать отдельную утилиту, которая бы сначала создавала бы зеркало БД, а затем поддерживала бы это зеркало: обновляла бы изменившиеся таблицы. Снова возвращаемся к постановке задачи - как сделать снимок всех данных с сервера, с которыми можно делать, что захотим. Бег по кругу (что раньше, курица или яйца)

PSP: Паш, сервер держит файлы открытыми. Как внешняя утилита получит к ним доступ?

Pasha: PSP пишет: Паш, сервер держит файлы открытыми. Как внешняя утилита получит к ним доступ? Внешняя утилита естественно будет открывать эти файлы тоже через letodb. Я думаю, она будет хранить таблицу, когда и какие файлы копировались (дата, размер). Если обнаружится, что файлы обновились, она их откроет, и дальше copy to. Перед копированием можно сделать попытку выдать FilLock. При таком способе, конечно, гарантии целостной копии не будет. Но без останова сервера сейчас это сделать нельзя. А с остановом - это задача совершенно тривиальная, но бесполезная.

nick_mi: В момент инициации бэкап Лето приостанавливает работу до окончания начавшихся транзакций, снимает размеры всех баз - это и будет "снимок БД". Лето начинает писать данные в "журнал изменеий". причем в журнал пишется только корректировка. Добавляемые записи не пишутся Для текущей работы берутся и основные базы, и журналы. , основываясь на размерах файлов БД. ЛЕТО выполняет бэкап только тех записей, которые попали в снимок. После окончания бэкапа журналы переносятся в основную БД. Сложно конечно, может и подтормаживать будет, но зато не надо останавливать сервер.

nick_mi: А может в журнал писать не изменения, а предыдущее состояние - только один раз, дальнейшие корректировки этой же записи писать не надо, а при бэкапе учитывать журнал и накрывать измененные записи старыми.

AlexMyr: Можно поконкретней про: nick_mi пишет: нимает размеры всех баз - это и будет "снимок БД" и про nick_mi пишет: ЕТО выполняет бэкап только тех записей, которые попали в снимок. и что такое: nick_mi пишет: После окончания бэкапа журналы переносятся в основную БД.

nick_mi: 1 Средствами ОС снять размеры файлов. Я думаю, задержка реакции Лето на запросі не будет очень длинной. 2. Пересчитать максимальную запись, имея размер файла не составит труда. в бэкап писать только записи <= максимальной рассчитаной. 3. В свете последнего уточнения журнал, естественно, возвращать в основную БД не требуется.

PSP: Еще вариант, с внешней утилитой и логом: 1. Сервер ведет лог изменений. Лог открыт монопольно, в него пишутся только алиас и номер изменившейся записи. 2. Запускается (по расписанию) внешняя утилита (назовем ее "Бэкап"), обращается к серверу (можно выставить какой-нибудь мьютекс), что она хочет обработать лог, продолжая пытаться отрыть файл лога. 3. Сервер заканчивает обрабатывать все транзакции, закрывает текущий лог, открывает новый и продолжает работать. 4. Бэкапу удается открыть старый лог, он его обрабатывает, копирует нужные записи, не мешая серверу работать. После окончания удаляет старый лог. и т.д.

Pasha: nick_mi пишет: В момент инициации бэкап Лето приостанавливает работу до окончания начавшихся транзакций Кстати, это мысль. Я собирался добавить на сервере такую фичу: временный запрет соединений, когда открытые соединения остаются, а новые блокируются. Это необходимо при профилактических работах на сервере, если его надо аккуратно остановить. Оповестить открытые коннекты о необходимости закрытия, и не допускать новые. Так же можно сделать временный запрет блокировок. Утилита архивации даст такую команду, и будет опрашивать, есть ли открытые блокировки. Когда их не будет, она отработает обновление зеркала, и вновь откроет блокировки.

AlexMyr: Pasha пишет: nick_mi пишет: цитата: В момент инициации бэкап Лето приостанавливает работу до окончания начавшихся транзакций Кстати, это мысль. Паша, такой вариант я предлагал AlexMyr пишет: Может использовать какой-то флаг (типа safety car), до флага все транзакции отрабатывают, а которые появились после флага становятся в очередь и ждут когда флаг уйдет с трассы, а в момент когда перед флагом место пусто (нет транзакций) запускается архивирование, флаг обнуляется, пошла нормальная работа. Как такой вариант?

Sergey Spirin: Pasha пишет: Оповестить открытые коннекты о необходимости закрытия, и не допускать новые. Паш, но это же и есть остановка сервера. Но ты же сам говоришь: Pasha пишет: Сейчас я не вижу, как сделать бэкап без остановки сервера. А останавливать его не получится. ADS-ный бэкап так и работает, ссылка, выше. Недопускает новые коннекты, ждет завершения старых. Интересно только, что если "не дожидается", то вываливается с ошибкой тайм-аута :)

AlexMyr: Sergey Spirin пишет: Интересно только, что если "не дожидается", то вываливается с ошибкой тайм-аута :) Наверное просит сделать попытку позже. Раскручу свой вариант еще: бэкап ждет некоторое время пока завершатся транзакции, если не дождался, делается следующая попытка дождаться, пропустив транзакции, к-е нервничают и так какое-то количество раз, если за отведенное количество не дождался, то завершаем попытки и выдаем сообщение "попробовать позже", если же дождался, то делаем бэкап, и продолжаем работу. Я так вижу процесс бэкапа в данный момент

Sergey Spirin: AlexMyr пишет: Я так вижу процесс бэкапа в данный момент Ты ссылку http://devzone.advantagedatabase.com/dz/content.aspx?Key=17&RefNo=090521-2178 посмотрел? Просто точно повторил ADS-ный вариант Сколько ждать в скольких попытках еще и параметризуется.

Pasha: Sergey Spirin пишет: Pasha пишет: цитата: Оповестить открытые коннекты о необходимости закрытия, и не допускать новые. Паш, но это же и есть остановка сервера. Но ты же сам говоришь: Нет, при этом все соединения останутся живые, только они на время бэкапа не смогут выполнять операции на обновление БД. А на чтение данных - смогут.

AlexMyr: Еще про роль бэкапа, у меня для 1с каждый день в 22:00 делается архивирование с помощью arc в файл вида storageYYYYMMDD, получается новый архив содержит на один день больше работы данных чем предыдущий, и когда что-то идет не так я могу развернуть архив за любой день и посмотреть что было до внештатной ситуации. Так что по мне лучше один раз притормозить сервер, чем постоянно следить за изменениями. Решать конечно Паше

AlexMyr: Sergey Spirin пишет: Ты ссылку http://devzone.advantagedatabase.com/dz/content.aspx?Key=17&RefNo=090521-2178 посмотрел? Просто точно повторил ADS-ный вариант Сколько ждать в скольких попытках еще и параметризуется. Нет, не заходил, только смотрел это Dima пишет: Да вроде есть такой механизм начиная с версии 8 http://www.hotsoft.ru/ADS/ads_80.htm

nick_mi: Я все-таки возвращаюсь к варианту, который я предложил. Приостановка сервера на время, пока делается "снимок БД", я думаю, это не долго, все зависит конечно от БД, далее пользователи работают, как и работали, параллельно идет бэкап, измененные записи затем накрываются из журнала БЫЛО. Возможно, он немного сложнее по реализации, но даст возможность пользователям работать паралельно с бэкапом.

Pasha: AlexMyr пишет: Наверное просит сделать попытку позже. Раскручу свой вариант еще: бэкап ждет некоторое время пока завершатся транзакции, если не дождался, делается следующая попытка дождаться, пропустив транзакции, к-е нервничают и так какое-то количество раз, если за отведенное количество не дождался, то завершаем попытки и выдаем сообщение "попробовать позже", если же дождался, то делаем бэкап, и продолжаем работу. Я так вижу процесс бэкапа в данный момент Да, наверное так и надо делать. В функции блокирования блокировок (эдакая тавтология) можно задать таймаут, в течении которого будет ожидание окончания всех операций с недопущением новых. Если операции завершились - возвращать успех, иначе - отменять блокировку блокировок. А полностью выгонять всех юзеров из базы - задача непростая. Да и делать это надо для других случаев. Блокирование новых коннектов - это отдельное действие.

Sergey Spirin: Pasha пишет: Нет, при этом все соединения останутся живые, только они на время бэкапа не смогут выполнять операции на обновление БД. А на чтение данных - смогут. Ну, это вопрос просто терминологии, что считать остановкой. Полная - не совсем полная, типа А так, ADS-ный вариант, похоже, и единственный...

Pasha: Sergey Spirin пишет: Ну, это вопрос просто терминологии, что считать остановкой. Полная - не совсем полная, типа А так, ADS-ный вариант, похоже, и единственный... На запросы сервер отвечать же будет. Правда, не на все.

PSP: Паша, как это будет выглядеть для клиентской стороны?

Pasha: Думаю, так. Если речь идет о windows, то на сервере в трее будет сидеть утилитка (написанная с помощью hwgui), которая при старте считает настройки: папку БД, папку зеркала, расширения файлов, команды архивации, график. Сначала она создаст зеркало. Затем по графику она будет просыпаться, попытается блокировать сервер, обновит зеркало и запустит архивацию. В меню трея можно будет увидеть ее состояние, ну и принудительно запустить архивацию. Можно еще дать ей функции блокировки новых соединений, ну и разблокировки соответственно. Сначала надо сделать поддержку команд блокировки сервером, а потом написать утилитку.

AlexMyr: Паша, зачем графический режим (hwgui), может быть проще, как для msde утилита osql в консоли, типа так: leto_backup -Uuser -Ppw -Tpath -Iip:port Не знаю, любой юзер может делать архив или только админ, или еще разрешения давать на работу с архивом (может лишнее это, права на создание архива) ? Допустим если путь не указать куда сохранять, то создаем архив, там где запущена утилита. АйПи и порт - может у кого два сервера крутится на одной машине. Можно еще какие параметры придумать.

Pasha: Все параметры затолкаем в ini. А интерфейс можно сделать и консольный, и gui. Запускать - хоть планировщиком.

PSP: Паша, так все-таки, как частичный стоп сервера будет восприниматься клиентским приложением? К примеру, клиент был подключен, начался бэкап, а клиент делает попытку записи в базу. Что будет? И что будет, если клиентское приложение не использует Leto_BeginTransaction() и Leto_CommitTransaction()?

Pasha: PSP пишет: Паша, так все-таки, как частичный стоп сервера будет восприниматься клиентским приложением? К примеру, клиент был подключен, начался бэкап, а клиент делает попытку записи в базу. Что будет? И что будет, если клиентское приложение не использует Leto_BeginTransaction() и Leto_CommitTransaction()? Любая попытка записи в БД, с использованием транзакции или нет, связана с попыткой блокировки. И на эту попытку клиент получит наш ответ Чемберлену: Не боимся буржуазного звона, ответим на ультиматум Керзона ! НЕТ ! rlock и fillock вернет .f., после dbappend() будет neterr()

PSP: Может быть не лишним будет сделать возможность проверки, разрешено писАть или нет, чтобы не доводить до ответа на "ультиматум Керзона", а? Ну, что-нибудь типа Leto_IsTransactionAllowed() -> .T. или .F.

Pasha: Так ведь любая попытка записи должна быть связана с проверкой. Зачем еще что-то дополнительно делать ? Как учила нас nantucket 20 лет назад, надо пару секунд попытаться выполнить блокировку, а если не получится - огорчиться.

PSP: Так-то оно так... Но Leto_IsTransactionAllowed() можно использовать для проверки с целью запретить юзерам даже пытаться редактировать данные. К примеру, в условии WHEN поля GET или еще где-то, где использование RLock(), FilLock() или DBAppend() не совсем корректно.

Pasha: PSP пишет: Так-то оно так... Но Leto_IsTransactionAllowed() можно использовать для проверки с целью запретить юзерам даже пытаться редактировать данные. К примеру, в условии WHEN поля GET или еще где-то, где использование RLock(), FilLock() или DBAppend() не совсем корректно. Не возражаю. Можно остановиться на таком синтаксисе: leto_LockUpdate([<.lOnOff.>]) При наличии параметра - включить/выключить блокировку изменений При его отсутствии - вернуть текущее состояние. Только для получения этого состояния клиенту прийдется посылать отдельный запрос на сервер, и все время так его опрашивать неэффективно.

PSP: Согласен.

Pasha: Я не забыл про эту тему, просто в силу обстоятельств могу уделять letodb немного времени. Уже почти все сделал. Возник такой ньюанс: перед копировании файлов сравниваю в том числе их размер. А он может различаться у оригинала и копии на 1-2 байта, если перед этим файл копировался средствами rdd. Приходится сравнивать размер "с погрешностью" до 2-х байт

Pasha: Сбросил на CVS

PSP: Pasha пишет: у оригинала и копии на 1-2 байта А время последнего изменения одинаково в этом случае?

Pasha: PSP пишет: А время последнего изменения одинаково в этом случае? Да, одинаково. Ситуация такая. При первом запуске таблица открыта, и, letobackup, обнаруживая это, открывает ее тоже через letodb, и создает копию средствами rdd. Затем закрывает копию, и устанавливает дату-время файла как на оригинале. А размер копии отличается от оригинала на 1-2 байта. Думаю, это несмертельно. Был еще ньюанс под windows с регистром: если имя файла набрано на верхнем регистре, то dbCreate (dbfcdx) его не создавал с параметром полное имя+расширение. Пришлось имя переводить в lower case. Еще ньюанс: если установлен режим Optimize=1 aka set hardcommit off, то надо отдельно перед созданием бэкапа делать сброс буферов, иначе копия будет неактуальной.

AlexMyr: Паша, при компиляции letobackup получил: gcc.exe: error: ../../lib/mingw/librddleto.a: No such file or directory в letobackup.hbp надо -l../../lib/librddleto.a т.к. при сборке letodb библиотека rddleto создается в папке /lib Спасибо за тулзу, будем тестировать

Pasha: Спасибо, учту. Еще наверное надо сделать свой вариант функции FileCopy, и отказаться от использования hbct. FileCopy из ct использует буфер размером всего 512 байт, что маловато, и скорость копирования при этом не самая высокая.

AlexMyr: Собрал, запускаю, получаю: C:\dev\letodb\utils\backup\>letobackup.exe Source directory is absent ... тут все правильно? [pre2] elseif ai[1] = "DATAPATH" cDB := ai[2] elseif ai[1] = "DATABASE" cDir := ai[2][/pre2]

AlexMyr: Вот мой letobackup.ini Server = //127.0.0.1:2812 DataPath = d:/data/temp Backup = .\backup\ Mask = *.dbf,*.fpt,*.dbt test_ta запустил и создал базы в d:/data/temp потом C:\dev\letodb\utils\backup\>letobackup.exe Connecting to //127.0.0.1:2812 Connected to Leto DB Server v.2.03 Trying to lock server... Success Get list of opened tables... 0 tables found Scanning directory tree... 0 files found Checking directories... Copying files... 0 files and 0 tables copied Unlocking server ... Success Backup finished Что еще надо прописать?

Pasha: Еще нужен параметр DataBase = / Этот параметр обязателен, странно что бэкап вообще начался без него, там же стоит проверка: elseif Empty( cDir ) ? "Source directory is absent ..." Return Nil В Datapath надо указать ту же папку, которая указана в letodb.ini. Это необходимо, поскольку бэкап использует файловый доступ, если файл не открыт letodb А в параметре DataBase - путь относительно Datapath Еще в параметре Backup = .\backup\ желательно задавать полный путь, если предполагается запускать архиватор, поскольку он с относительным путем не найдет, что архивировать.

AlexMyr: AlexMyr пишет: тут все правильно? elseif ai[1] = "DATAPATH" cDB := ai[2] elseif ai[1] = "DATABASE" cDir := ai[2] тут ничего не напутано? cDb относится к DATAPATH, а cDir к DATABASE? letodb.ini DataPath = d:/data EnableFileFunc = 1 letobackup.ini Server = //127.0.0.1:2812 Database = /temp/ или Database = / DataPath = d:/data Backup = .\backup\ Mask = *.dbf,*.fpt,*.dbt не работает!

AlexMyr: Сделал маленький тест: letodb.ini DataPath = d:/data EnableFileFunc = 1 [pre2]Function Main Local cPath := "//127.0.0.1:2812/", adir:={} REQUEST LETO RDDSETDEFAULT( "LETO" ) adir := leto_Directory(cPath+"/data","D") // результат 0 adir := leto_Directory(cPath,"D") // результат >0 ?len(adir) for i:=1 to len(adir) ?valtype(adir[i,1]),adir[i,1] next return nil[/pre2] Когда изменил letobackup.ini Server = //127.0.0.1:2812 DataPath = / DataBase = /temp/ Backup = .\backup\ Mask = *.dbf,*.fpt,*.dbt тогда сработало: C:\dev\letodb\utils\backup\>letobackup.exe Connecting to //127.0.0.1:2812 Connected to Leto DB Server v.2.03 Trying to lock server... Success / //127.0.0.1:2812 Get list of opened tables... 0 tables found Scanning directory tree... 39 files found Checking directories... Copying file /test2.dbf 39 files and 0 tables copied Unlocking server ... Success Backup finished

AlexMyr: Базы лежат в d:/data/temp letobackup.ini Server = //127.0.0.1:2812 DataPath = / DataBase = /temp Backup = .\backup\ Mask = *.dbf,*.fpt,*.dbt letobackup создает каталог ./backup/temp, Connecting to //127.0.0.1:2812 Connected to Leto DB Server v.2.03 Trying to lock server... Success / //127.0.0.1:2812 Get list of opened tables... 0 tables found Scanning directory tree... 4 files found Checking directories... Copying file /temp/Nakl2.fpt 4 files and 0 tables copied Unlocking server ... Success Backup finished находит 4 файла, НО в backup/temp файлы не копирует!

AlexMyr: еще момент, базы переложил из /data/temp в /data, запускаю letobackup, отработал, файлы скопировал, но поставил им всем дату 16.01.12 16:41, вот!

Pasha: Не перепутано. Я сделал точно такой же letodb.ini, и точно такой же letobackup.ini с Database = /temp/ создал d:\data\temp бросил туда 1 файл запустил letobackup получил результат: Connecting to //127.0.0.1:2812 Connected to Leto DB Server v.2.03 Trying to lock server... Success Get list of opened tables... 0 tables found Scanning directory tree... 1 files found Checking directories... Copying file /temp/temp.dbf 1 files and 0 tables copied Unlocking server ... Success Backup finished Почему-то не отрабатывает leto_directory, поскольку "0 files found" "0 tables found" - так и должно быть, так как через letodb ничего не открыто.. а если в функции GetFiles после строки LOCAL aDir := leto_Directory( cDir, "D" ), ad поставить отладочную печать: ? cDir, len(aDir) что получится ?

AlexMyr: Pasha пишет: что получится ? уже пробовал, результат 0

Pasha: AlexMyr пишет: еще момент, базы переложил из /data/temp в /data, запускаю letobackup, отработал, файлы скопировал, но поставил им всем дату 16.01.12 16:41, вот! А у оригинальных файлов дата другая ? В случае копирования через файловую систему (а в этом случае так и происходит) дату-время копии файла устанавливает функция FileCopy()

AlexMyr: Pasha пишет: А у оригинальных файлов дата другая ? Да другая, 24.02.12 14:45

Pasha: Функции из ct я заменил на функции из rtl (там и буфер поболее, аж 8К), кое-что поправил в блокировке сервера, сегодня скину. Но с остальными чудесами честно говоря непонятно. У себя я их не обнаружил.

AlexMyr: Буду дальше тестировать

Dima: Насколько сильно начинает тормозить основное приложение когда LetoDB начал копировать базы ? У меня основная программа на Clipper а копирование и архивацию делает программа написанная на Harbour. Когда начинается копирование баз то в основной программе тормоза получаются не детские. Это хорошо видно там ,где работа с базой идет через бровс.

Pasha: Здесь немного разный подход. В случае копирования на клиппере или харборе используется файловый доступ. Если копирование выполняется на сервере, то файлы открываются в режиме разделения, и копирование выполняется медленно. Если копирование запускается с клиента, то все выполняется намного хуже. letodb открывает файлы монопольно. Бэкап выполняется на сервере. Если изменившився файл не открыт, то он копируется обычными файловыми операциями, то есть быстро. Если изменившийся файл открыт через letodb, то letobackup открывает его через letodb, создает его копию, и заполняет ее через стандартные методы доступа rdd, тоже быстро, поскольку монопольно. Перед копирорванием выполняется блокировка сервера, то есть ожидается завершение текущих операций модификации данных, и во время копирования не допускаются новые операции. На время копирования основная программа не сможет модифицировать данные. Но можно задать режим без этой фичи. В этом случае копирование будет выполняться прозрачно, незаметно для основной программы, но не будет гарантии целостности данных. Копия будет как срез БД. Так как это все выполняется на сервере, копирование выполняется достаточно быстро. Полное копирование БД размером 300М у меня заняло время до 5 секунд. Если копируются только изменившиеся данные, время копирования будет еще меньше, намного.

Dima: Pasha Спасибо за подробный ответ !

Dima: Pasha пишет: Полное копирование БД размером 300М у меня заняло время до 5 секунд Да уж не плохо. У меня расшаренная база 470 мегабайт по сети копируется за 2.5 минуты средcтвами Harbour

AlexMyr: Выкачал заново letodb, собрал, проверил letobackup, работает Паша, спасибо

Dima: Pasha пишет: Так как это все выполняется на сервере, копирование выполняется достаточно быстро. Полное копирование БД размером 300М у меня заняло время до 5 секунд. Если копируются только изменившиеся данные, время копирования будет еще меньше, намного. Каким образом копировать только изменившиеся данные ? Не понятно как удается вложиться в 5 секунд при копировании базы в 300 метров. Провел эксперимент [pre2] proc main local a:=seconds() use karta new // размер 80 мегабайт *copy file karta.dbf to karta1.dbf *? seconds()-a // 3 секунды *wait dbCreate( "dbf_new", dbStruct()) use dbf_new exclusive new select karta go top while ! eof() dbf_new->(dbAppend()) for i := 1 to FCount() dbf_new->(FieldPut( i, karta->(FieldGet( i )) )) next if Deleted() dbf_new->(dbDelete()) endif skip enddo ? seconds()-a // 24 секунды wait return [/pre2] Copy to сработало быстрее в 8 раз

AlexMyr: Так, тестирую на удаленной машине и получаю C:\dev\letodb\utils\backup\>letobackup.exe Connecting to //x.x.x.x:2812/ Connected to Leto DB Server v.2.03 Trying to lock server... Success Get list of opened tables... 0 tables found Scanning directory tree... 2 files found Checking directories... Copying file /rel1.dbf Error BASE/2012 Open error: e:/data_dbf/rel1.dbf (DOS Error 3) Called from __COPYFILE(0) Called from MAKECOPY(285) Called from BACKUP(228) Called from MAIN(172) т.е. нашел два файла, а при копировании путь не найден

Pasha: AlexMyr пишет: Так, тестирую на удаленной машине и получаю Так я делал эту утилиту для запуска на сервере, там, где расположена БД Если расчитывать на бэкап с клиентской машины, тогда копирование неоткрытых файлов прийдется выполнять не файловыми операциями, а средствами letodb, что будет заметно медленнее.

AlexMyr: Pasha пишет: Так я делал эту утилиту для запуска на сервере, там, где расположена БД Ясно, так работает.

Pasha: Dima пишет: Каким образом копировать только изменившиеся данные ? Не понятно как удается вложиться в 5 секунд при копировании базы в 300 метров. Провел эксперимент Если делать бэкап неоткрытой БД, то 300М у меня скопировалось за 6.5-7 сек (не 5, урезаю осетра, говорил "на глаз") Открытая БД 300М копируется за 40 сек, это средствами rdd. Copy to не использую, так как тогда бекап надо делать в пределах видимости letodb. Можно сделать отдельную опцию для использования copy to Отслеживается изменение таблицы в целом, изменение отдельных записей не отслеживается

Pasha: Пробую использовать __dbCopy. И оказывается, что letobackup блокирует сервер и сама себе не дает копировать таблицы. Прийдется наверное не делать блокировку для пользователя, который блокировал сервер.

Dima: Pasha пишет: Если делать бэкап неоткрытой БД, то 300М у меня скопировалось за 6.5-7 сек (не 5, урезаю осетра, говорил "на глаз") Как происходит бэкап неоткрытой БД ? Функцию MakeCopy я смотрел. Копирование происходит в следующем куске кода и я ни как не пойму как можно уложиться за 7 секунд при копировании базы в 300 метров коли база копируется целиком. В чем же фишка то ? [pre2] select leto_old leto_SetSkipBuffer( 1000 ) set order to 0 go top while ! eof() dbf_new->(dbAppend()) for i := 1 to FCount() dbf_new->(FieldPut( i, leto_old->(FieldGet( i )) )) next if Deleted() dbf_new->(dbDelete()) endif skip enddo [/pre2]

Pasha: Если файл не открыт letodb, то работает другая ветка: [pre2] if ASCAN(aTables, {|a| Lower(a[2]) == Lower(af[1])}) != 0 // не эта elseif ! IsMemoFile( aTables, Lower(af[1]) ) // а простое копирование файла ?? Padr( "Copying file " + af[1], MaxCol() ) __CopyFile( cDB + af[1], cNewFile ) hb_FSetDateTime( cNewFile, af[3], af[4] ) nFiles ++ endif[/pre2]

Dima: Pasha пишет: Если файл не открыт letodb, то работает другая ветка: Это я промахнулся ;)



полная версия страницы