API резервного копирования баз данных
API резервного копирования баз данных.
sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); int sqlite3_backup_step(sqlite3_backup *p, int nPage); int sqlite3_backup_finish(sqlite3_backup *p); int sqlite3_backup_remaining(sqlite3_backup *p); int sqlite3_backup_pagecount(sqlite3_backup *p);
API резервного копирования копирует содержимое одной базы данных в другую. Он полезен для создания резервных копий баз данных или для копирования баз данных в оперативной памяти в постоянные файлы или из них.
См. также: Использование API резервного копирования SQLite
SQLite держит открытую транзакцию записи в файле целевой базы данных на протяжении всего процесса резервного копирования. База данных источника заблокирована для чтения только во время чтения; она не заблокирована постоянно на протяжении всего процесса резервного копирования. Таким образом, резервное копирование может выполняться на активной базе данных источника без предотвращения других подключений к базе данных от чтения или записи в базу данных источника во время выполнения резервного копирования.
Для выполнения операции резервного копирования:
- sqlite3_backup_init() вызывается один раз для инициализации резервного копирования,
- sqlite3_backup_step() вызывается один или несколько раз для передачи данных между двумя базами данных, и, наконец,
- sqlite3_backup_finish() вызывается для освобождения всех ресурсов, связанных с операцией резервного копирования.
sqlite3_backup_init()
Аргументы D и N в sqlite3_backup_init(D,N,S,M) — это соединение с базой данных, связанное с целевой базой данных, и имя базы данных соответственно. Имя базы данных — "main" для основной базы данных, "temp" для временной базы данных или имя, указанное после ключевого слова AS в операторе ATTACH для присоединённой базы данных. Аргументы S и M, переданные в sqlite3_backup_init(D,N,S,M), идентифицируют соединение с базой данных и имя базы данных базы данных источника соответственно. Источник и целевые соединения с базой данных (параметры S и D) должны быть разными, иначе sqlite3_backup_init(D,N,S,M) завершится с ошибкой.
Вызов sqlite3_backup_init() завершится неудачей, вернув NULL, если уже открыта транзакция чтения или чтения/записи в целевой базе данных.
Если при выполнении sqlite3_backup_init(D,N,S,M) возникнет ошибка, то возвращается NULL, а код ошибки и сообщение об ошибке сохраняются в целевом соединении с базой данных D. Код ошибки и сообщение об ошибке для неудачного вызова sqlite3_backup_init() можно получить с помощью функций sqlite3_errcode(), sqlite3_errmsg() и/или sqlite3_errmsg16(). Успешный вызов sqlite3_backup_init() возвращает указатель на объект sqlite3_backup. Объект sqlite3_backup может использоваться с функциями sqlite3_backup_step() и sqlite3_backup_finish() для выполнения указанной операции резервного копирования.
sqlite3_backup_step()
Функция sqlite3_backup_step(B,N) скопирует до N страниц между базами данных источника и назначения, указанными объектом sqlite3_backup B. Если N отрицательно, копируются все оставшиеся страницы источника. Если sqlite3_backup_step(B,N) успешно скопирует N страниц и ещё есть страницы для копирования, то функция вернёт SQLITE_OK. Если sqlite3_backup_step(B,N) успешно завершит копирование всех страниц из источника в назначение, то она вернёт SQLITE_DONE. Если при выполнении sqlite3_backup_step(B,N) возникнет ошибка, то возвращается код ошибки. Помимо SQLITE_OK и SQLITE_DONE, вызов sqlite3_backup_step() может вернуть SQLITE_READONLY, SQLITE_NOMEM, SQLITE_BUSY, SQLITE_LOCKED или расширенный код ошибки SQLITE_IOERR_XXX.
Функция sqlite3_backup_step() может вернуть SQLITE_READONLY, если
- целевая база данных была открыта только для чтения, или
- целевая база данных использует журналирование write-ahead-log, и размеры страниц назначения и источника отличаются, или
- целевая база данных — база данных в оперативной памяти, и размеры страниц назначения и источника отличаются.
Если sqlite3_backup_step() не может получить необходимую файловую блокировку, то вызывается функция обработчика занятости (если она указана). Если обработчик занятости возвращает ненулевое значение до того, как блокировка станет доступной, то вызывающему объекту возвращается SQLITE_BUSY. В этом случае вызов sqlite3_backup_step() можно повторить позже. Если соединение с базой данных источника используется для записи в базу данных источника во время вызова sqlite3_backup_step(), то сразу возвращается SQLITE_LOCKED. Опять же, в этом случае вызов sqlite3_backup_step() можно повторить позже. Если возвращается SQLITE_IOERR_XXX, SQLITE_NOMEM или SQLITE_READONLY, то нет смысла повторять вызов sqlite3_backup_step(). Эти ошибки считаются фатальными. Приложение должно принять тот факт, что операция резервного копирования завершилась неудачно, и передать дескриптор операции резервного копирования в sqlite3_backup_finish() для освобождения связанных ресурсов.
Первый вызов sqlite3_backup_step() получает эксклюзивную блокировку целевого файла. Эксклюзивная блокировка не освобождается до тех пор, пока не будет вызван sqlite3_backup_finish() или пока операция резервного копирования не будет завершена, и sqlite3_backup_step() не вернёт SQLITE_DONE. Каждый вызов sqlite3_backup_step() получает совместную блокировку на базе данных источника, которая длится на протяжении всего вызова sqlite3_backup_step(). Поскольку база данных источника не блокируется между вызовами sqlite3_backup_step(), база данных источника может быть изменена в середине процесса резервного копирования. Если база данных источника изменяется внешним процессом или через соединение с базой данных, отличное от используемого операцией резервного копирования, то резервное копирование автоматически перезапускается следующим вызовом sqlite3_backup_step(). Если база данных источника изменяется с помощью того же соединения с базой данных, что и операция резервного копирования, то база данных резервного копирования автоматически обновляется одновременно.
sqlite3_backup_finish()
Когда sqlite3_backup_step() вернул SQLITE_DONE или когда приложение хочет отказаться от операции резервного копирования, приложение должно уничтожить sqlite3_backup, передав его в sqlite3_backup_finish(). Интерфейс sqlite3_backup_finish() освобождает все ресурсы, связанные с объектом sqlite3_backup. Если sqlite3_backup_step() ещё не вернул SQLITE_DONE, то любая активная транзакция записи в целевой базе данных откатывается. Объект sqlite3_backup становится недействительным и больше не может использоваться после вызова sqlite3_backup_finish().
Значение, возвращаемое sqlite3_backup_finish, — SQLITE_OK, если не произошло ошибок sqlite3_backup_step(), независимо от того, завершил ли sqlite3_backup_step() свою работу или нет. Если во время любого предыдущего вызова sqlite3_backup_step() для того же объекта sqlite3_backup произошла ошибка из-за отсутствия памяти или ошибки ввода-вывода, то sqlite3_backup_finish() возвращает соответствующий код ошибки.
Возврат SQLITE_BUSY или SQLITE_LOCKED из sqlite3_backup_step() — это не постоянная ошибка и не влияет на значение, возвращаемое sqlite3_backup_finish().
sqlite3_backup_remaining() и sqlite3_backup_pagecount()
Функция sqlite3_backup_remaining() возвращает количество страниц, которые ещё нужно скопировать, по завершении последнего вызова sqlite3_backup_step(). Функция sqlite3_backup_pagecount() возвращает общее количество страниц в базе данных источника по завершении последнего вызова sqlite3_backup_step(). Значения, возвращаемые этими функциями, обновляются только вызовом sqlite3_backup_step(). Если база данных источника изменяется таким образом, что изменяет размер базы данных источника или оставшееся количество страниц, эти изменения не отражаются в выводе sqlite3_backup_pagecount() и sqlite3_backup_remaining() до следующего вызова sqlite3_backup_step().
Одновременное использование дескрипторов баз данных
Соединение с базой данных источника может использоваться приложением для других целей во время или в процессе инициализации операции резервного копирования. Если SQLite скомпилирован и настроен для поддержки потокобезопасных соединений с базой данных, то соединение с базой данных источника можно использовать параллельно из других потоков.
Однако приложение должно гарантировать, что целевое соединение с базой данных не передаётся ни одному другому API (ни одним потоком) после вызова sqlite3_backup_init() и до соответствующего вызова sqlite3_backup_finish(). SQLite в настоящее время не проверяет, не обращается ли приложение некорректно к целевому соединению с базой данных, поэтому код ошибки не сообщается, но операции могут тем не менее работать неправильно. Использование целевого соединения с базой данных во время выполнения резервного копирования также может привести к тупиковой ситуации с мьютексом.
Если используется режим совместного кэша, приложение должно гарантировать, что к совместному кэшу, используемому целевой базой данных, не обращаются во время выполнения резервного копирования. На практике это означает, что приложение должно гарантировать, что к файлу диска, в который выполняется резервное копирование, не обращается ни одно соединение в процессе, а не только то конкретное соединение, которое было передано в sqlite3_backup_init().
Сам объект sqlite3_backup частично потокобезопасен. Несколько потоков могут безопасно делать несколько одновременных вызовов sqlite3_backup_step(). Однако API sqlite3_backup_remaining() и sqlite3_backup_pagecount() не являются строго говоря потокобезопасными. Если они вызываются одновременно с другим потоком, вызывающим sqlite3_backup_step(), возможно, они вернут некорректные значения.
Альтернативы использованию API резервного копирования
Другие методы безопасного создания согласованной резервной копии базы данных SQLite включают:
- Команда VACUUM INTO.
- Утилита sqlite3_rsync.
См. также списки объектов, констант и функций.
SQLite is in the Public Domain.
https://sqlite.org/c3ref/backup_finish.html