SSD Nodes Learn 8GB RAM — $66/rok
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-01

SQLite na VPS w produkcji: konfiguracja i limity

SQLite sprawdza się w małej aplikacji na jednym VPS. Sprawdź tryb WAL, busy_timeout, replikację Litestream oraz limity pojedynczego procesu i pliku bazy.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Kiedy SQLite jest właściwą produkcyjną bazą danych na VPS

Uruchomienie SQLite w środowisku produkcyjnym na VPS jest właściwym wyborem dla większości małych aplikacji. Powód jest prosty: jeden proces na jednej maszynie, zapisujący do jednego pliku, nie potrzebuje serwera baz danych. Nie ma demona, którego działanie trzeba nadzorować, portu, który trzeba chronić zaporą sieciową, hasła, które trzeba okresowo zmieniać, ani drugiej maszyny, którą trzeba utrzymywać. Zapytanie jest wywołaniem funkcji, a nie komunikacją sieciową, dlatego strona wykonująca czterdzieści zapytań generuje czterdzieści wywołań funkcji.

Ograniczenie jest konkretne i rzeczywiste. SQLite zezwala na zapis tylko jednemu procesowi jednocześnie w całym pliku bazy danych, a pliku nie można współdzielić między dwiema maszynami. Oba ograniczenia nie stanowią problemu w przypadku pojedynczego VPS uruchamiającego pojedynczą aplikację. Oba stają się krytyczne natychmiast po odejściu od takiej architektury. W tym przewodniku opisano ustawienia zapewniające bezpieczne działanie SQLite na serwerze, ciągłe tworzenie kopii zapasowych za pomocą Litestream oraz moment, w którym należy zakończyć korzystanie z SQLite.

Najpierw zainstaluj narzędzie wiersza poleceń. Wszystkie poniższe czynności wykonano w systemie Ubuntu 24.04.

sudo apt update
sudo apt install -y sqlite3
sqlite3 --version

Zostanie wyświetlona wersja rozpoczynająca się od 3., a następnie data kompilacji i skrót źródłowy. W lipcu 2026 system Ubuntu 24.04 udostępnia SQLite 3.45.1. Aplikacja prawdopodobnie nie korzysta z tego pliku binarnego: większość środowisk uruchomieniowych języków programowania dołącza własną kopię biblioteki SQLite, często nowszą. Przed użyciem nowej funkcji należy więc sprawdzić wersję zgłaszaną przez sterownik bazy danych.

Dlaczego tryb WAL jest pierwszą zmianą, którą należy wprowadzić

Domyślnie SQLite używa dziennika wycofywania zmian. Przed zmianą strony kopiuje jej oryginalną wersję do pliku -journal, a następnie modyfikuje bazę danych bezpośrednio. Aby wykonać tę operację bezpiecznie, uzyskuje wyłączną blokadę całego pliku. Dlatego każdy odczyt oczekuje, gdy trwa dowolna operacja zapisu. Na laptopie nie jest to zauważalne. Na serwerze WWW jeden wolny zapis wstrzymuje każde żądanie korzystające z bazy danych.

Tryb WAL (write-ahead log) odwraca tę kolejność. Proces zapisujący dołącza nowe strony do oddzielnego pliku -wal i pozostawia główną bazę danych bez zmian. Procesy odczytujące nadal odczytują główny plik z migawki utworzonej w chwili rozpoczęcia odczytu. Dzięki temu odczyty nie blokują zapisu, a zapis nie blokuje odczytów. Później punkt kontrolny kopiuje zgromadzone strony WAL z powrotem do głównej bazy danych. Ta jedna zmiana w największym stopniu decyduje o tym, że SQLite nadaje się do użycia za aplikacją internetową.

Włączenie trybu WAL i potwierdzenie jego trwałego zastosowania

mkdir -p ~/app
sqlite3 ~/app/app.db "PRAGMA journal_mode=WAL;"

Polecenie wyświetla wal. Ten wynik nie jest informacyjny wyłącznie dekoracyjnie. PRAGMA journal_mode zwraca tryb, w którym faktycznie znajduje się baza danych, dlatego odpowiedź delete oznacza, że zmiana się nie powiodła i nadal używany jest dziennik wycofywania.

Tryb WAL jest trwały. Jest flagą w nagłówku bazy danych, a nie ustawieniem połączenia. Dlatego wykonuje się to polecenie raz dla każdego pliku bazy danych, a każde późniejsze połączenie dziedziczy to ustawienie, także po ponownym uruchomieniu systemu. Należy to potwierdzić przy użyciu nowego połączenia.

sqlite3 ~/app/app.db "PRAGMA journal_mode;"

Następnie należy utworzyć tabelę i sprawdzić, jakie pliki pojawią się na dysku.

sqlite3 ~/app/app.db <<'SQL'
CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT NOT NULL);
INSERT INTO notes (body) VALUES ('first row');
SQL
ls -l ~/app/

Teraz istnieją trzy pliki: app.db, app.db-wal i app.db-shm. Plik -wal zawiera zatwierdzone strony, dla których nie wykonano jeszcze punktu kontrolnego. Plik -shm jest indeksem pamięci współdzielonej, który każde połączenie mapuje, aby wszystkie połączenia miały zgodny obraz zawartości WAL. Oba pliki należą do bazy danych i nie są plikami tymczasowymi. Skopiowanie samego pliku app.db podczas działania aplikacji powoduje utworzenie pliku pozbawionego wszystkich najnowszych zatwierdzonych zmian. Usunięcie pliku app.db przy pozostawieniu dwóch pozostałych plików sprawi, że SQLite zastosuje nieaktualne strony WAL do dowolnego nowego pliku utworzonego pod tą nazwą. W ten sposób można uszkodzić nową bazę danych podczas próby jej zresetowania.

Ustawienia połączenia wymagane przez każdą aplikację produkcyjną

Tylko journal_mode jest przechowywane w bazie danych. Każde pozostałe ustawienie poniżej dotyczy konkretnego połączenia. Oznacza to, że aplikacja musi je ustawić dla każdego otwieranego połączenia, w tym dla każdego połączenia tworzonego w tle przez pulę.

PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON;

busy_timeout = 5000 nakazuje SQLite ponawiać próby dostępu do zablokowanej bazy danych przez maksymalnie 5000 milisekund, zanim zwrócony zostanie błąd database is locked. Wartość domyślna wynosi 0. Domyślnie SQLite kończy działanie błędem natychmiast, gdy dwóch zapisujących jednocześnie próbuje uzyskać dostęp do bazy. Ustawienie tej jednej wartości eliminuje większość błędów blokad przypisywanych samemu SQLite.

synchronous = NORMAL jest właściwym ustawieniem w trybie WAL, ale należy rozumieć związany z nim kompromis. Przy wartości FULL SQLite wywołuje fsync dla WAL przy każdym zatwierdzeniu transakcji. Przy wartości NORMAL synchronizacja odbywa się podczas punktów kontrolnych. Dokumentacja SQLite jasno opisuje konsekwencje: po awarii zasilania lub twardym resecie transakcje nie są już trwałe. Utrata zasilania nie powoduje uszkodzenia bazy danych. Utracone zostają jedynie ostatnie zatwierdzenia, które nie zostały zapisane na dysku. Na VPS jest to zazwyczaj właściwy kompromis, ponieważ usuwa wywołanie fsync ze ścieżki każdego pojedynczego zapisu.

foreign_keys = ON jest domyślnie wyłączone w celu zachowania zgodności wstecznej i dotyczy konkretnego połączenia. Schemat zawierający wiele klauzul REFERENCES nie wymusza żadnych ograniczeń, dopóki każde połączenie nie włączy tego ustawienia.

Jeszcze jedno ustawienie ma znaczenie dopiero na późniejszym etapie. SQLite automatycznie wykonuje punkt kontrolny, gdy WAL przekroczy 1000 stron. Operację wykonuje połączenie, które w danym momencie zakończy transakcję. Samo w sobie nie stanowi to problemu. Sytuacja zmienia się, gdy działa Litestream, ponieważ Litestream musi kontrolować moment wykonywania punktów kontrolnych.

Dlaczego database is locked nadal występuje po ustawieniu busy_timeout

Jest to błąd, który skłania użytkowników do powrotu do Postgres. Ma jedną konkretną przyczynę.

Limit czasu oczekiwania instaluje procedurę obsługi stanu zajętości, ale SQLite nie gwarantuje jej wywołania.

Jeśli SQLite ustali, że wywołanie procedury obsługi stanu zajętości mogłoby doprowadzić do zakleszczenia, zwróci aplikacji SQLITE_BUSY zamiast wywoływać tę procedurę.

Zakleszczenie, którego SQLite unika, występuje podczas przekształcania transakcji. Samo BEGIN w SQLite oznacza BEGIN DEFERRED. Jeśli pierwsza instrukcja po nim to SELECT, transakcja jest transakcją odczytu. Gdy późniejsze UPDATE w tej samej transakcji wymaga przekształcenia jej w transakcję zapisu, a inne połączenie wykonało zapis od rozpoczęcia odczytu, SQLite nie może zmusić połączenia do oczekiwania. Migawka jest już nieaktualna, a oczekiwanie doprowadziłoby jedynie do wzajemnego zakleszczenia obu połączeń. Dokumentacja bezpośrednio określa ten wynik:

Kolejne instrukcje zapisu przekształcą transakcję w transakcję zapisu, jeśli będzie to możliwe, albo zwrócą SQLITE_BUSY.

Ustawiony limit czasu wynoszący 5000 milisekund nie jest w ogóle uwzględniany. Błąd jest zwracany natychmiast, dlatego wygląda to tak, jakby ustawienie nie działało.

Naprawa wymaga jednego słowa.

BEGIN IMMEDIATE;
UPDATE notes SET body = 'edited' WHERE id = 1;
COMMIT;

BEGIN IMMEDIATE uzyskuje blokadę zapisu na początku, przed wykonaniem jakichkolwiek odczytów. Nie dochodzi do przekształcenia transakcji, więc nie ma zakleszczenia, którego należałoby unikać. Procedura obsługi stanu zajętości jest stosowana, a połączenie oczekuje na swoją kolej zamiast kończyć się błędem. Transakcje tylko do odczytu powinny pozostać odroczone. Każda transakcja zawierająca zapis powinna być natychmiastowa.

Druga przyczyna błędów blokady jest trudniejsza do wykrycia: utrzymywanie otwartej transakcji zapisu podczas powolnych operacji. SQLite szereguje operacje zapisu, dlatego transakcja, która zostaje otwarta, wywołuje zewnętrzne API przez sieć, a następnie wykonuje commit, blokuje wszystkie pozostałe operacje zapisu na czas trwania tego wywołania. Należy odczytać wymagane dane, zamknąć transakcję, wykonać powolną operację, a następnie otworzyć krótką transakcję zapisu w celu zapisania wyniku.

Ciągła kopia zapasowa za pomocą Litestream

Nocna kopia może utracić zapisy z całego dnia, a uruchomienie cp względem używanej bazy danych SQLite może utworzyć kopię, której nie da się otworzyć. Bezpieczne są dwa rozwiązania. sqlite3 app.db ".backup /path/to/backup.db" korzysta z interfejsu kopii online SQLite i działa względem używanej bazy danych. Litestream idzie dalej: monitoruje WAL i stale wysyła zmiany do magazynu obiektowego. W ten sposób maksymalna możliwa utrata danych zmniejsza się z jednego dnia do około sekundy.

Litestream jest pojedynczym plikiem binarnym Go uruchamianym obok aplikacji. Nie działa między aplikacją a bazą danych. Aplikacja zapisuje dane w SQLite dokładnie tak jak wcześniej, a Litestream odczytuje WAL i przesyła zmienione dane.

cd /tmp
curl -fsSL -O https://github.com/benbjohnson/litestream/releases/download/v0.5.14/litestream-0.5.14-linux-x86_64.deb
sudo dpkg -i litestream-0.5.14-linux-x86_64.deb
litestream version

Wersja v0.5.14 jest wersją opisaną na oficjalnej stronie instalacji systemu Linux w lipcu 2026, a v0.5.15 została wydana 21 July 2026. Należy zmienić wersję w obu wierszach tak, aby odpowiadała bieżącemu tagowi na stronie wydań. Jeśli VPS ma architekturę arm64, należy zamiast tego pobrać pasujący pakiet arm64.

Plik konfiguracji znajduje się w /etc/litestream.yml. Należy zacząć od lokalnej repliki plikowej, ponieważ pozwala to sprawdzić cały proces bez używania danych uwierzytelniających do chmury.

dbs:
  - path: /home/appuser/app/app.db
    replica:
      type: file
      path: /var/backups/litestream/app

Należy zwrócić uwagę, że pole ma nazwę replica i występuje w liczbie pojedynczej. Litestream 0.5 zastąpił tablicę replicas z serii 0.3 pojedynczym blokiem repliki. Konfiguracja zawierająca dwa wpisy kończy się teraz błędem podczas uruchamiania. Wiele przewodników innych firm nadal pokazuje starą tablicę, dlatego należy skopiować powyższą strukturę, a nie pierwszy przykład znaleziony w wynikach wyszukiwania. W serii 0.5 zmieniono również nazwę podkomendy litestream wal na litestream ltx, ponieważ zmienił się format kopii zapasowej na dysku.

Przed włączeniem jakichkolwiek funkcji należy sprawdzić, czy konfiguracja jest poprawnie analizowana.

sudo litestream databases -config /etc/litestream.yml

Następnie należy ręcznie sprawdzić pełny cykl. Ta forma pomija plik konfiguracji i replikuje jedną bazę danych do jednej ścieżki.

mkdir -p /tmp/replica
litestream replicate ~/app/app.db file:///tmp/replica/app

Polecenie działa na pierwszym planie i pozostaje uruchomione. W drugiej powłoce należy zapisać wiersz, a następnie odtworzyć replikę do nowego pliku.

sqlite3 ~/app/app.db "INSERT INTO notes (body) VALUES ('written after replication started');"
litestream restore -o /tmp/restored.db file:///tmp/replica/app
sqlite3 /tmp/restored.db "SELECT count(*) FROM notes;"

Licznik obejmuje nowy wiersz. Jeśli go nie obejmuje, zmiana nie została jeszcze zsynchronizowana. Litestream wysyła dane w interwale sync-interval, którego wartość domyślna wynosi 1 second, dlatego należy odczekać i ponownie wykonać odtwarzanie. Ta jedna sekunda jest również punktem odtwarzania. Awaria powoduje utratę najwyżej zapisów z ostatniego interwału synchronizacji. Żadna konfiguracja nie zmniejszy tej wartości do zera.

W przypadku rzeczywistego magazynu należy zastąpić blok repliki adresem URL S3. Działa to zarówno z Amazon S3, jak i z magazynami obiektowymi zgodnymi z S3, oferowanymi przez innych dostawców.

dbs:
  - path: /home/appuser/app/app.db
    replica:
      url: s3://your-bucket-name/app
      region: us-east-1

snapshot:
  interval: 24h
  retention: 24h

Nie należy przechowywać danych uwierzytelniających w tym pliku. Litestream odczytuje LITESTREAM_ACCESS_KEY_ID i LITESTREAM_SECRET_ACCESS_KEY ze środowiska, dlatego należy umieścić je w pliku drop-in systemd należącym do root i ustawić tryb 600.

Powyższe wartości migawek są wartościami domyślnymi, a domyślna retencja może być zaskakująca. Retencja określa, jak długo Litestream przechowuje migawki i należące do nich pliki. Określa więc również, jak daleko wstecz można odtworzyć dane. Dwadzieścia cztery godziny oznacza, że błędna migracja zauważona w środę rano jest już nieodwracalna na podstawie stanu z poniedziałku. Należy ustawić retention: 168h na tydzień i uwzględnić koszt dodatkowego miejsca.

Sprawdź przywracanie, zanim będzie potrzebne

litestream restore -o /tmp/check.db /home/appuser/app/app.db
sqlite3 /tmp/check.db "PRAGMA integrity_check;"
sqlite3 /tmp/check.db "SELECT count(*) FROM notes;"

Po podaniu ścieżki bazy danych litestream restore wyszukuje pasującą replikę w /etc/litestream.yml i pobiera ją. PRAGMA integrity_check wyświetla ok dla poprawnego pliku. Każdy inny wynik oznacza, że przywrócona kopia nie nadaje się do użytku. Należy uruchamiać to zgodnie z harmonogramem za pomocą usługi i zegara systemd oraz odczytywać dane wyjściowe. Dopóki kopia zapasowa nie zostanie przywrócona przynajmniej raz, nie ma pewności, że działa.

Uruchamianie Litestream za pomocą systemd

Pakiet Debian instaluje jednostkę litestream, która odczytuje /etc/litestream.yml.

sudo systemctl enable litestream
sudo systemctl start litestream
sudo journalctl -u litestream -f

Prawidłowe działanie jest sygnalizowane nazwą każdej bazy danych z konfiguracji, a następnie brakiem komunikatów poza okresowymi wpisami o synchronizacji. Błąd no such file or directory dotyczący ścieżki bazy danych oznacza, że ścieżka w konfiguracji jest nieprawidłowa albo proces nie może jej odczytać. Jednostka jest domyślnie uruchamiana jako root, co daje temu zadaniu większe uprawnienia, niż jest to potrzebne. Litestream musi mieć możliwość odczytu i zapisu zarówno bazy danych, jak i katalogu, w którym się ona znajduje, ponieważ korzysta z plików -wal i -shm umieszczonych obok bazy danych. Należy więc przypisać jej konto używane już przez aplikację.

# /etc/systemd/system/litestream.service.d/override.conf
[Service]
User=appuser
Group=appuser

Należy zastosować te ustawienia za pomocą sudo systemctl daemon-reload i sudo systemctl restart litestream. Skonfigurowanie dedykowanego konta usługi z minimalnymi uprawnieniami zajmuje kilka minut. Dzięki temu agent kopii zapasowych nie działa jako drugi proces root na serwerze.

Jeśli maszyna będzie kiedyś odtwarzana od zera, istotna jest kolejność uruchamiania. Baza danych powinna zostać odtworzona przed uruchomieniem aplikacji. litestream restore akceptuje -if-db-not-exists, które kończy działanie z kodem 0, gdy plik już istnieje, dlatego można bezpiecznie uruchamiać je przy każdym rozruchu. Należy umieścić je w wierszu ExecStartPre jednostki aplikacji. Nowy VPS pobierze wtedy bazę danych, a istniejący VPS nie wykona żadnej operacji. litestream replicate ma odpowiadającą opcję -restore-if-db-not-exists, jeśli preferowane jest przechowywanie tej konfiguracji w jednym miejscu.

Gdzie SQLite przestaje sprawdzać się na VPS

Systemy plików dostępne przez sieć. Tego ograniczenia nie można obejść konfiguracją. Tryb WAL wymaga, aby każdy proces korzystający z bazy danych współdzielił niewielki obszar pamięci. Udostępnia go plik -shm. Dokumentacja SQLite określa tę zasadę bez wyjątków:

Wszystkie procesy korzystające z bazy danych muszą działać na tym samym komputerze; WAL nie działa w systemie plików dostępnym przez sieć.

Baza danych umieszczona na zamontowanym udziale NFS (network file system) lub SMB może ulec uszkodzeniu. Żadna dyrektywa pragma temu nie zapobiega. W tym przypadku występuje różnica, którą często się pomija. Sieciowe urządzenie blokowe, czyli rozwiązanie używane przez większość dostawców VPS do podłączania dodatkowej pamięci masowej, jest widoczne w systemie Linux jako zwykły dysk ze zwykłym systemem plików. To rozwiązanie jest prawidłowe. Zamontowany udział plików nim nie jest.

Drugi serwer aplikacji. Żadne ustawienie tego nie umożliwi. Gdy te same dane muszą być obsługiwane przez dwa komputery, potrzebna jest baza danych komunikująca się przez sieć. Należy zaplanować tę zmianę, póki jest na to czas.

Obciążenia z dużą liczbą operacji zapisu. Możliwość wykonywania zapisu przez tylko jednego zapisującego naraz wynika z formatu pliku i nie można jej dostroić. Krótkie operacje zapisu są tanie, ponieważ każdy commit jest dopisywany do WAL. Dlatego przepustowość zależy bardziej od opóźnienia dysku przy małych operacjach zapisu niż od procesora. Zobacz NVMe a pamięć masowa SATA SSD na VPS, aby sprawdzić, jak wygląda ta różnica. Rzeczywistym problemem są długie transakcje, ponieważ ustawiają wszystkie pozostałe operacje zapisu w kolejce.

Zapytania analityczne. SQLite jest magazynem wierszowym przeznaczonym do obsługi transakcji. Pulpit nawigacyjny skanujący sto milionów wierszy to inne zadanie, przeznaczone dla innego narzędzia. Temat ten opisano w DuckDB a SQLite w zastosowaniach serwerowych.

VACUUM podczas replikacji. Pełna operacja VACUUM przepisuje cały plik bazy danych. Oznacza to, że Litestream musi ponownie przesłać cały plik. Dokumentacja Litestream odradza wykonywanie tej operacji podczas aktywnej replikacji. Należy zatrzymać replikator, wykonać vacuum, uruchomić go ponownie i oczekiwać utworzenia nowej pełnej migawki.

Dwa replikatory dla jednej bazy danych. Nie należy uruchamiać dwóch procesów Litestream dla tej samej bazy danych ani tego samego miejsca docelowego repliki. Dokumentacja jednoznacznie wskazuje, że zapobieganie takiej sytuacji należy do obowiązków administratora. W przeciwnym razie powstaje replika, której nie można odtworzyć.

Czego Litestream nie obejmuje

Litestream chroni plik bazy danych i nic więcej. Przesłane pliki, konfiguracja aplikacji, certyfikaty TLS (transport layer security) oraz pliki jednostek nadal wymagają osobnej obsługi. Należy połączyć go z zaplanowanymi szyfrowanymi kopiami zapasowymi poza serwerem przy użyciu restic, aby objąć ochroną oba elementy. Jeśli maszyna jest nowa, sekcja pierwsze dziesięć minut na nowym VPS-ie obejmuje konfigurację konta użytkownika i zapory sieciowej, które w tym poradniku uznaje się za już wykonane.

FAQ

Czy SQLite wystarcza do zastosowania produkcyjnego?

W przypadku jednej aplikacji na jednym serwerze — tak, pod warunkiem włączenia trybu WAL, ustawienia limitu czasu oczekiwania i wykonywania ciągłych kopii zapasowych. Istotne ograniczenia mają charakter strukturalny: jednocześnie może zapisywać tylko jeden proces, a baza może znajdować się na jednym komputerze. Aplikacja mieszcząca się w tych ograniczeniach korzysta z bazy bez przeskoku sieciowego i bez osobnego procesu do monitorowania. Aplikacja, która ich nie spełnia, wymaga bazy danych w architekturze klient-serwer. Żadne dostrajanie tego nie zmieni.

Dlaczego nadal otrzymuję database is locked po ustawieniu busy_timeout?

Ponieważ SQLite pomija procedurę obsługi zajętości, gdy oczekiwanie mogłoby spowodować zakleszczenie. Transakcja rozpoczynająca się od samego BEGIN jest odroczona: początkowe SELECT umieszcza ją w transakcji odczytu, a późniejszy zapis musi podnieść jej poziom. Jeśli w międzyczasie inny proces wykonał zapis, SQLite natychmiast zwraca SQLITE_BUSY zamiast wywoływać procedurę obsługi zajętości, ponieważ migawka odczytu jest już nieaktualna. Każdą transakcję, która będzie wykonywać zapis, należy rozpoczynać od BEGIN IMMEDIATE, aby blokada zapisu została uzyskana od razu i aby obowiązywał limit czasu oczekiwania.

Czy można przechowywać bazę SQLite na magazynie sieciowym?

Nie na systemie plików dostępnym przez sieć, takim jak NFS lub SMB. Tryb WAL wymaga, aby wszystkie procesy współdzieliły pamięć za pośrednictwem pliku -shm, a dokumentacja SQLite stwierdza, że każdy proces korzystający z bazy musi działać na tym samym komputerze hosta. Sieciowe urządzenie blokowe podłączone przez dostawcę to inny przypadek: Linux widzi na nim zwykły dysk ze zwykłym systemem plików, więc SQLite działa prawidłowo.

Czy Litestream jest potrzebny, jeśli kopie zapasowe są już wykonywane co noc?

Zależy to od ilości danych, których utratę można zaakceptować. Zadanie uruchamiane co noc oznacza możliwość utraty maksymalnie dwudziestu czterech godzin zapisów. Litestream synchronizuje dane mniej więcej raz na sekundę, więc awaria powoduje utratę około ostatniej sekundy. Jest również bezpieczniejszy niż kopiowanie pliku bazy za pomocą cp, ponieważ kopia może zostać utworzona w trakcie zapisu do bazy. Litestream obejmuje tylko bazę danych, dlatego obok niego należy uruchomić ogólną kopię zapasową plików.

#sqlite#wal#litestream#backups#production