Как сделать инкрементную резервную копию базы данных SQLite?

Я хочу делать резервные копии базы данных с высокой частотой, но стоимость полного резервного копирования неприемлема. Кажется, у SQLite нет API для прямого добавочного резервного копирования. Но я обнаружил, что есть обратные вызовы уведомлений об изменении данных, которые кажутся полезными. https://www.sqlite.org/c3ref/update_hook.html Параметры обратные вызовы - это тип операции, имя базы данных, имя таблицы и идентификатор строки. Однако я не знаю, возможно ли сгенерировать резервную информацию (например, оператор SQL) для этой строки даты с помощью этой информации, не зная подробной информации о таблице. Что означает, существует ли общий метод создания резервной копии для этой операции для таблиц с другой структурой? Я знаю, что есть некоторые исключения, когда обратный вызов не будет вызываться, и я думаю, что это приемлемо, если я периодически делаю полное резервное копирование.


person iuradz    schedule 19.03.2015    source источник
comment
SQLite имеет API резервного копирования: sqlite.org/backup.html.   -  person Colonel Thirty Two    schedule 20.03.2015
comment
@ColonelThirtyTwo И это делает полные резервные копии.   -  person CL.    schedule 20.03.2015
comment
Да. И это стоило слишком дорого, чтобы часто делать полный бэк.   -  person iuradz    schedule 20.03.2015
comment
Возможный дубликат Как я могу создавать добавочные резервные копии mysql базы данных   -  person Paul Sweatte    schedule 03.10.2015
comment
Возможный дубликат Как сделать инкрементное резервное копирование для SQLite?   -  person Bernardo Ramos    schedule 15.01.2017
comment
Возможный дубликат Есть ли способ обновить базу данных SQLITE с помощью дельты?   -  person Paul Sweatte    schedule 21.01.2017


Ответы (1)


Я думал об этой идее, она официально не одобрена SQLite, но в теории звучит очень правдоподобно.

API резервного копирования SQLite, по сути, позволяет вам получить рабочий снимок файла базы данных в реальном времени. Точно так же VACCUM INTO позволяет вам обновить существующий файл резервной копии базы данных. https://www.sqlite.org/lang_vacuum.html#vacuuminto

Это просто старая добрая резервная копия, нам нужна инкрементная резервная копия (вроде git)

Предположим, мы хотим делать резервную копию базы данных каждый час, и это база данных размером 1 ГБ с относительно небольшим количеством операций записи, хранение 24 ГБ в день звучит как излишество.

Мы можем воспользоваться преимуществами формата файла SQLite, который по сути представляет собой фиксированный 100-байтовый заголовок + (размер_страницы * количество страниц). SQLite всегда будет писать за пределами страницы. Page_size и num_pages хранятся в 100-байтовом заголовке. См. спецификацию хранилища https://www.sqlite.org/fileformat.html.

Итак, что мы можем сделать, так это создать эталонный файл, который представляет собой просто файл со списком хэшей. Скажем, мы используем sha256 (именно его использует новая версия git), поэтому это будет файл (например, backups/2020-02-22-19-12-00.txt)

sha256(header)
sha256(page1)
sha256(page2)
sha256(page3)

И мы храним соответствующие страницы в виде отдельных файлов, как это делает git в каталоге объектов.

Например, объекты/ab/cdef12343..

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

В качестве альтернативы вы можете просто загрузить файлы подкачки в любой из поставщиков облачных хранилищ, например GCS, S3, Azure Blobs, пространства DO. Это может дать резервную копию нескольких регионов.

Поскольку мы не храним дубликаты страниц, общий размер файлов всех резервных копий довольно мал по сравнению с размером базы данных * число_резервных копий.

Вы даже можете использовать файл хэшей как способ синхронизации/восстановления файла SQLite. Вот как Dropbox/rsync синхронизирует файлы. Файл хэшей сообщает нам, какие страницы изменились, и мы загружаем только измененные объекты и обновляем эти диапазоны в файле.

person user3893988    schedule 06.03.2020