Úplná záloha webu je dump databáze plus archiv souborů včetně složky uploads, pořízené konzistentně, uložené aspoň na dvou místech, z nichž jedno je mimo webový server, a ověřené testovací obnovou. Na našem testovacím serveru většina klasických chyb vedla k záloze, která vznikla bez jediného varování: problém se ukázal až při obnově. Níže najdete pravidlo 3-2-1 jednoduše, tabulku „co zálohovat, čím, jak často a jak ověřit“, měření pro mysqldump, kompresi a restic a testovací obnovu krok za krokem.
Jak jsme testovali
10. listopadu 2026 na testovacím serveru: kontejner Ubuntu 24.04.5 (2 vCPU, 8 GB RAM), nginx 1.24.0, PHP-FPM 8.3.6, dvě samostatné instance MariaDB 10.11.14, WordPress 6.4.3 s 6 001 články, 450 fotografiemi (330 MB) a tabulkou logů s 1,5 milionu řádků; dump databáze měl 404 MB. Dumpy jsme pořizovali za nepřetržitého zápisu „objednávek“, porovnali jsme gzip, zstd a xz, zálohovali jsme pomocí restic 0.16.4 do samostatného adresáře, který sloužil jako vzdálené úložiště, nasimulovali jsme ztrátu disku a obnovili web do čisté instance MariaDB. Takto se choval testovací server; nejde o data ze serverů RichHost.
Pravidlo 3-2-1 pro web na sdíleném hostingu
Pravidlo 3-2-1 znamená tři kopie dat na dvou různých médiích nebo systémech, přičemž jedna kopie je jinde. Pro web na sdíleném hostingu to vypadá takto. Kopie první: samotný běžící web. Kopie druhá: záloha, kterou dělá váš hosting a uchovává mimo webový server. Kopie třetí: vaše vlastní záloha u jiného poskytovatele, v cloudovém úložišti nebo na vašem počítači. Nerozhoduje počet kopií, ale jejich nezávislost: pokud jsou všechny tři na jednom disku nebo dostupné z jednoho účtu, máte jednu kopii, jen třikrát.
Aby pravidlo fungovalo, platí ještě dvě podmínky. Uchovávejte zálohy za několik dní nebo týdnů, ne jen tu poslední, protože napadení nebo poškození webu můžete odhalit pozdě. A každé nastavení ověřte aspoň jednou obnovou, jinak nevíte, zda zálohu vůbec máte.
Co zálohovat, čím, jak často a jak ověřit
| Co | Nástroj | Jak často | Jak ověřit |
|---|---|---|---|
| Databáze (články, objednávky, uživatelé, nastavení) | mariadb-dump nebo mysqldump s --single-transaction, poté zstd |
Denně; u e-shopu několikrát denně | Poslední řádek „Dump completed“, zstd -t, testovací import a počty řádků |
| Uploads: fotky, PDF, soubory zákazníků | tar + zstd -3 nebo restic |
Denně nebo po každém větším nahrání | Počet souborů v záloze, několik náhodných obrázků se po obnově otevře |
| Kód: jádro, šablony, pluginy | tar + zstd, git pro vlastní šablonu |
Před každou aktualizací | Obnovený web vrací 200, přihlášení do administrace funguje |
| Konfigurace: wp-config.php, .htaccess, úlohy cron | Spolu se soubory; úlohy cron sepsané v textovém souboru | Po každé změně | Soubory jsou v archivu, úlohy odpovídají aktuálním |
| Pošta, DNS záznamy | DNS zóna exportovaná do textového souboru, pošta přes poštovního klienta nebo panel | Měsíčně a po změnách | Porovnat zónu s ostrou pomocí dig |
Tabulky logů, statistik a cache pluginů často váží víc než veškerý obsah. Na testovacím serveru tvořila tabulka logů zhruba 350 MB ze 404 MB dumpu. Její vyčištění zálohy zmenší a zrychlí; podívejte se na náš návod k tématu optimalizace databáze na hostingu.
Databáze: proč záleží na --single-transaction
Skript nepřetržitě vytvářel „objednávky“: jeden řádek ve wp_posts a čtyři řádky ve wp_postmeta v jedné transakci, zhruba 45 objednávek za sekundu. O dvě sekundy později se spustil dump v jednom ze tří režimů.
| Režim dumpu | Objednávky bez dat v záloze | Nejdelší čekání na zápis |
|---|---|---|
Bez zámků (--skip-lock-tables), 3 běhy |
3, 7 a 5 | 0,17 s |
Výchozí (--lock-tables) |
0 | 3,84 s: všechny zápisy čekaly na dump |
--single-transaction --quick, 3 běhy |
0, 0 a 0 | 0,18 s |
Bez zámků čte dump tabulky jednu po druhé: wp_postmeta před wp_posts. Objednávky uložené mezi těmito dvěma čteními skončily v záloze bez částky, e-mailu a způsobu platby. Takový dump se naimportuje bez chyb a zjistíte to až ve chvíli, kdy se zákazník zeptá na svou objednávku. Výchozí režim udrží zálohu konzistentní, ale po celou dobu dumpu blokuje zápisy: u větší databáze to znamená minuty, kdy e-shop nemůže přijímat objednávky. --single-transaction pořídí konzistentní snapshot InnoDB bez zamykání. U tabulek MyISAM nepomůže, takže staré tabulky převeďte na InnoDB.
mariadb-dump --single-transaction --quick --default-character-set=utf8mb4 wp > db.sql tail -1 db.sql -- Dump completed on 2026-11-10 14:51:46
Bez zátěže trvaly oba režimy stejně dlouho: 3,2-3,9 sekundy pro 404 MB. Rozdíl se projeví jen tehdy, když se do databáze zapisuje, což u e-shopu znamená v pracovní době.
Soubory: jaký kompresor použít
Každý kompresor běžel v jednom vlákně na stejných datech.
| Kompresor | Soubory webu, 388 MB | Dump databáze, 404 MB |
|---|---|---|
gzip -6 |
16,6 s, 341,7 MB (88 %) | 9,2 s, 85,9 MB (21 %) |
zstd -3 |
1,5 s, 343,4 MB (88 %) | 1,9 s, 79,8 MB (20 %) |
zstd -19 |
149,4 s, 333,8 MB (86 %) | 350,1 s, 64,8 MB (16 %) |
xz -6 |
207,2 s, 335,0 MB (86 %) | 289,3 s, 64,3 MB (16 %) |
Fotky JPEG jsou už komprimované, takže archiv souborů se téměř nezmenší, ať použijete cokoli. Dump se zmenší pětkrát. zstd -3 nabídl nejlepší kompromis: 5krát až 11krát rychlejší než gzip při o něco menším souboru. Maximální úrovně zstd a xz ušetřily u dumpu zhruba o 15 MB víc za cenu pěti minut procesorového času, což je na sdíleném hostingu zbytečná zátěž.
Přírůstkové zálohy: co přináší deduplikace v restic
restic a borg dělí data na bloky a ukládají jen nové. První záloha webu s dumpem měla 791 MB (427 MB v repozitáři, protože restic komprimuje). Pak:
- Jeden nový článek, jedna fotka o velikosti 454 KB a 20 objednávek: druhá záloha přidala 4,6 MB.
- Smazání 1 000 nejstarších řádků tabulky logů, jak to dělají čisticí pluginy: třetí záloha přidala 359,6 MB, téměř celý dump.
- Stejná změna, ale s dumpem s jedním řádkem na INSERT (
--skip-extended-insert): přibylo 7,6 MB.

Běžný dump vkládá stovky řádků do každého příkazu INSERT. Smazání řádků na začátku tabulky posune hranice všech následujících příkazů a restic pak zbytek souboru vidí jako nový. Dump s jedním řádkem na INSERT se dobře deduplikuje, ale má to svou cenu: na testovacím serveru trval jeho import 507 sekund místo 35. Pokud platíte za úložiště podle objemu a obnovujete zřídka, vyplatí se to; pokud záleží na rychlosti obnovy, zůstaňte u běžného dumpu a uchovávejte méně verzí. Borg jsme neměřili: v testovacím kontejneru se kvůli nekompatibilní verzi Pythonu nespustil, takže čísla platí jen pro restic.
export RESTIC_REPOSITORY=sftp:backup@storage.example.net:/restic export RESTIC_PASSWORD_FILE=~/.restic-pass restic init restic backup ~/backup/db.sql ~/web/example.com/public_html restic forget --keep-daily 14 --keep-weekly 8 --prune restic check
Adresu repozitáře nahraďte svou vlastní. Heslo k repozitáři držte mimo server: bez něj zálohu nikdo nedešifruje, ani vy.
Testovací obnova: jak ověřit, že záloha funguje
Nasimulovali jsme nejhorší případ: zastavili jsme databázi, smazali celý adresář „serveru“ včetně lokálních záloh a obnovili web z restic do nové instance MariaDB s prázdnou složkou webu.
restic restore latest --target /srv/restore
Summary: Restored 3523 files/dirs (789.971 MiB) in 0:02
mariadb -e "CREATE DATABASE wp"
mariadb wp < db.sql
curl -s -o /dev/null -w "%{http_code}\n" http://bench.test:8122/
200
curl -sI "http://bench.test:8122/wp-json/wp/v2/posts?per_page=1" | grep -i x-wp-total
X-WP-Total: 6002
Od začátku do odpovědi 200 uběhlo 23 sekund: 4 na soubory, 19 na import databáze. Počty článků a objednávek i nejvyšší ID odpovídaly ostrému webu, nová fotka se vrátila se stejným kontrolním součtem a titulky v nelatinkových písmech zůstaly v pořádku. Mimochodem, náš první pokus selhal naší vlastní chybou: restic uložil cesty přesně tak, jak jsme mu je předali, a soubory skončily v jiné složce, než skript očekával. Přesně takové detaily testovací obnova odhalí.
Minimální měsíční kontrola:
- Ověřte integritu archivu:
zstd -t,gzip -tneborestic check. - Zkontrolujte, že dump končí řádkem „Dump completed“.
- Naimportujte dump do samostatné testovací databáze a porovnejte počty článků, objednávek a uživatelů s ostrým webem.
- Nasaďte soubory na testovací subdoménu a ověřte odpověď 200, přihlášení do administrace a několik starých obrázků.
- Zapište si, jak dlouho to trvalo: to je váš skutečný čas obnovy.
V podstatě jde o stejný postup jako při přesunu WordPressu na jiný hosting, jen bez přepnutí domény.
Čtyři selhání, která jsme na testovacím serveru zopakovali
Záloha bez složky uploads
Archiv vytvořený s --exclude=wp-content/uploads měl 15 MB místo 361 MB. Po obnově vracela úvodní stránka 200 a REST API vypsalo všech 6 002 článků, ale každá fotka vracela 404: 450 příloh v databázi, 0 souborů na disku. Web vypadá živě, dokud neotevřete libovolný článek. Uploads se často vynechávají kvůli limitu velikosti, proto kontrolujte počet souborů v záloze.
Zálohy jen na stejném serveru
Když zmizel adresář „serveru“, zmizely spolu s webem i dump, archiv souborů a kontrolní součty vedle nich: No such file or directory. Web zachránila jen kopie v samostatném úložišti. Archivy navíc nikdy neukládejte do kořenového adresáře webu, odkud si je kdokoli stáhne přes URL. Pro adresář se zálohami stačí práva 700 pro složku a 600 pro soubory.
Useknutý soubor
Záloha useknutá na 60 % (plný disk nebo přerušený přenos) neprojde přes zstd -t a hlásí „Read error (39) : premature end“; gzip hlásí „unexpected end of file“. Horší je nekomprimovaný dump: import se zastavil na ERROR 1064, ale do té doby stihl vytvořit 7 ze 13 tabulek a 3 825 z 9 304 řádků wp_posts. Tabulky uživatelů a kategorií chyběly, takže se nikdo nemohl přihlásit. Useknutý dump se snadno pozná: na konci chybí řádek „Dump completed“.
Špatná znaková sada nebo collation
Dump pořízený s --default-character-set=latin1 doběhl bez chyb, ale v 5 986 z 6 001 titulků se cyrilice změnila na otazníky. Tato ztráta je trvalá: správné bajty v souboru prostě nejsou. Další varianta: dump bez řádku SET NAMES importovaný klientem běžícím v latin1 (jako klient mariadb na testovacím serveru v relaci bez UTF-8 locale). Titulky se objevily jako rozsypaný čaj typu „ДоÑтавка“, zatímco stejný soubor se s --default-character-set=utf8mb4 naimportoval správně. Třetí případ jsme emulovali tak, že jsme v dumpu nahradili collation tou, kterou MySQL 8 vytváří ve výchozím stavu: MariaDB 10.11 odpověděla ERROR 1273 (HY000): Unknown collation: 'utf8mb4_0900_ai_ci' a nevytvořila žádnou tabulku. Řešení: nahradit collation podporovanou, například utf8mb4_unicode_520_ci, a importovat znovu.
Pokud je to vaše situace, udělejte toto
| Pokud | Udělejte |
|---|---|
| Blog nebo firemní prezentace, změny jednou týdně | Zálohy hostingu plus vlastní týdenní záloha databáze a souborů jinde, testovací obnova jednou za čtvrtletí |
| E-shop nebo web, který přijímá objednávky | Dump s --single-transaction několikrát denně, soubory denně, testovací obnova každý měsíc |
| Zálohy se nevejdou do limitu úložiště | restic nebo borg s deduplikací a čištěním tabulek logů, bez vynechání uploads |
| Přechod z MySQL 8 na MariaDB | Otestujte import před přepnutím domény; při ERROR 1273 nahraďte collation v dumpu |
| Web je už napadený nebo nefunguje | Nejdřív najděte příčinu a uložte současný stav, pak obnovte zálohu z doby před incidentem |
| Nevíte, kdy proběhla poslední záloha | Nastavte upozornění na chybějící zálohu a ještě dnes proveďte testovací obnovu |
Pokud web už nefunguje, začněte hledáním příčiny v logech serveru: často jde o plugin nebo plný disk a návrat ke včerejší záloze by jen smazal nové objednávky. Spouštějte zálohovací skript podle plánu pomocí úloh cron na hostingu, přidejte kontrolu „Dump completed“ a zstd -t a nechte monitoring serveru, ať vás upozorní, když něco selže.
Zálohy u RichHost
Všechny hostingové tarify RichHost zahrnují průběžné zálohy do cloudu: kopii uloženou mimo webový server. Podle pravidla 3-2-1 přidejte vlastní zálohu jinde a čas od času ji ověřte obnovou na testovací subdoménu. Podpora odpovídá na dotazy k zálohám od 10:00 do 20:00 kyjevského času, obvykle zhruba do 30 minut.
Časté dotazy
Stačí zálohy od mého hostingu?
Pro většinu incidentů ano, ale pravidlo 3-2-1 vyžaduje ještě jednu nezávislou kopii. Zachrání vás, když je problém s vaším účtem nebo fakturací, nebo když potřebujete starší verzi, než hosting uchovává.
Jak často zálohovat web?
Tak často, kolik dat si můžete dovolit ztratit. Blogu stačí denní nebo týdenní zálohy, e-shop potřebuje několik dumpů databáze denně. Soubory se mění méně často než databáze a lze je zálohovat méně často.
Můžu dělat dump databáze, když web běží?
Ano, s --single-transaction pro tabulky InnoDB. Na testovacím serveru takový dump neztratil žádnou objednávku a neblokoval zápisy, zatímco dump bez zámků ztratil při každém běhu data 3-7 objednávek.
Jak otestovat zálohu, aniž bych rozbil ostrý web?
Obnovte ji do samostatné databáze a na testovací subdoménu, nikdy přes ostrý web. Porovnejte počty článků a objednávek, otevřete několik stránek a obrázků a přihlaste se do administrace.



