Disc de server 100% plin (0 octeți liberi): Recuperarea unei baze de date prăbușite când rm şi apt Eșuează din cauza lipsei de inoduri/spațiu¶
Numerele de urgență diferă în funcție de țară. Această pagină folosește 911, numărul pentru Statele Unite și Canada. Multe alte țări folosesc 112, 999 sau un alt număr. Găsiți numărul pentru țara dvs.
Descoperirea că un server Linux de producție a lovit 100% utilizarea discului (0 bytes free) sau 100% utilizarea inodului (df -i) în timp ce rulează o bază de date activă PostgreSQL, MySQL/InnoDB, MariaDB sau SQLite este unul dintre cele mai periculoase moduri de eroare în administrarea sistemelor. La zero octeți sau zero inoduri libere, criza cascadă rapid: nucleul sistemului de operare nu mai poate crea socket-uri de domeniu Unix în /tmp sau /var/run, bash nu reușește să completeze tab-ul deoarece nu poate scrie shell pipe-uri temporare, apt sau dnf nu poate rula pentru a curăța pachetele deoarece managerii de pachete necesită fișiere de blocare temporare, iar motorul bazei de date se blochează în mijlocul unui jurnal de scriere anticipată (WAL) punct de control sau refuză să se închidă în mod curat deoarece nu poate aloca un singur bloc de 4 kiloocteți (0,004 megaocteți) pentru .pid sau blocați fișierul. Mai rău încă, administratorii panicați rulează adesea rm -rf /var/log/*.log pe fișiere jurnal de mai mulți gigabyte și urmăriți îngrozit ca df -h încă raportează 100% Use% (0 Avail), sau se șterg fatal pg_wal (pg_xlog) sau ib_logfile0 pentru a elibera spațiu, corupând permanent baza de date dincolo de recuperarea tranzacțiilor. Dacă ați șters accidental fișiere de bază de date critice în timpul unei încercări de curățare, opriți imediat și treceți la accidental rm -rf sau Shift-Delete remontare doar pentru citire și sculptare inod; dacă hardware-ul de stocare de bază generează erori I/O sau s-a blocat împotriva scrierilor, consultați-vă Modul de doar citire bruscă SSD și NVMe și salvarea dezactivată TRIM sau recuperarea fișierelor Word, Excel, PDF și baze de date corupte. Dacă această întrerupere afectează sistemele de siguranță a vieții spitalului, expedierea de urgență sau utilitățile publice critice, sunați la numărul local de urgență (911 în Statele Unite și Canada, 112 în întreaga Uniune Europeană, 999 în Regatul Unit) sau consultați directorul nostru global de numere de urgență.
Fă asta acum¶
- ** NU ștergeți
pg_wal/,pg_xlog/,pg_multixact/,ib_logfile*,undo_*, sau-wal/-shmfișiere pentru a face spațiu**: ștergerea fișierelor de jurnal Write-Ahead sau InnoDB reface/anulați în timp ce o bază de date este prăbușită sau nu este verificată, distruge singura înregistrare a paginilor necommitate și în timpul zborului. O bază de date cu un disc plin este 100% recuperabilă odată ce spațiul este eliberat; o bază de date cu ale cărei fișiere WAL au fost șterse manualrmva suferi corupție ireversibilă a arborelui B și a mormanului. - Diagnosticați în 5 secunde dacă nu mai aveți blocuri de disc (
df -h), din sistemul de fișiere inode (df -i), sau ținând deschise fișiere deconectate (lsof +L1)*: - Fugi
df -hpentru a verifica capacitatea blocului șidf -ipentru a verifica capacitatea inodului. Un server cu 50 de gigaocteți (53,6 miliarde de octeți) spațiu liber pe disc va genera în continuareNo space left on device (ENOSPC)dacădf -ispectacoleIUse% = 100%(cauzată de obicei de milioane de fișiere mici de sesiune, cache sau spool de e-mail). - Dacă
df -hspectacole100%folosit (0 Avail) chiar și după ce ai fugitrmpe fișiere jurnal uriașe, rulațisudo lsof +L1. Orice fișier șters curmîn timp cenginx,rsyslog,docker,postgres, saumysqldîncă deține un descriptor de fișier deschis și continuă să consume 100% din blocurile sale de disc până când procesul repornește sau trunchiați descriptorul direct. - Gigaocteți liberi de spațiu într-o secundă fără a reporni demonii prin trunchierea fișierelor deschise la locul lor (
: > /path/to/logfilesau: > /proc/<pid>/fd/<n>)*: - În loc de
rm /var/log/syslog(care lasă blocurile blocate de loggerul care rulează), zero fișierul în loc folosind redirecționarea shell null:sudo sh -c ': > /var/log/syslog'sausudo truncate -s 0 /var/log/syslog. - Dacă ai alergat deja
rmpe un fișier jurnal masiv șidf -hnu a scăzut, găsiți ID-ul de proces (PID) și descriptor de fișier (FD) însudo lsof +L1și trunchiați-l direct prin interfața procfs kernel:sudo sh -c ': > /proc/<PID>/fd/<FD>'. Spațiul se va întoarce ladf -hinstantaneu. - Deblocați camera de respirație de urgență instantanee activată
ext4/ext3prin scăderea procentului de bloc rădăcină rezervat (tune2fs -m 1): Implicit,ext4rezervă 5 la sută din întreaga partiție (25 gigabytespe a500 gigabytedisc) exclusiv pentruUID 0(root), adică servicii non-root precumpostgres(UID 109),mysql, șiwww-datalovitNo space left on devicela o utilizare de 95 la sută. Recuperați 80% din această rezervă online într-o secundă, fără timp de nefuncționare, rulândsudo tune2fs -m 1 /dev/sda1(sau dispozitivul dvs. de blocare rădăcină de lafindmnt /). - Vacuum
systemd-journaldjurnalele binare și cache-urile de pachete vechi în siguranță: Rulațisudo journalctl --vacuum-size=50M(care se rotește în siguranță și purifică fișierul binar/var/log/journalarhive până la 50 megaocteți) șisudo apt-get clean(sausudo dnf clean all), care șterge descărcat.deb/.rpmarhive în/var/cache/apt/archives/fără a fi nevoie să scrieți în baza de date dpkg. - Odată ce cel puțin 1 gigabyte până la 5 gigaocteți (1,07 miliarde până la 5,36 miliarde de octeți) de spațiu sunt liberi, deschideți baza de date în modul de utilizator unic sau de recuperare pentru a-și finaliza punctul de control WAL înainte de a permite traficul clientului: lăsați PostgreSQL, MySQL/InnoDB sau SQLite să-și reia jurnalul de scriere anticipată (
WAL), ștergeți paginile murdare în fișierele de date principale și reciclați în mod curat segmentele WAL umflate înainte de a redeschide firewall-ul aplicației sau serverul web.
Danger
Nu fugi niciodată pg_resetwal (sau pg_resetxlog) pe PostgreSQL sau innodb_force_recovery = 6 pe MySQL pur și simplu pentru că discul s-a umplut: Rulează pg_resetwal șterge indicatorii jurnalului de tranzacții și forțează PostgreSQL să înceapă cu pagini de date pe jumătate scrise, garantând pierderea silențioasă a rândurilor, chei primare duplicate și arbori B cu chei externe sparte. În 99,9% din blocările bazei de date cu disc plin, pur și simplu eliberarea de la 2 gigabytes la 10 gigabytes (2,1 miliarde până la 10,7 miliarde de octeți) de spațiu pe partiție și pornirea demonului bazei de date permite în mod normal recuperarea automată a erorilor (REDO faza) pentru a termina curat cu zero pierderi de date.
Arborele de decizie: server cu spațiu zero și triajul bazei de date prăbușite¶
Utilizați acest arbore de decizie pentru a identifica motivul pentru care sistemul de operare raportează ENOSPC (No space left on device) și selectați calea exactă de recuperare nedistructivă:
flowchart TD
Start["Aruncarea serverului sau a bazei de date: nu a mai rămas spațiu pe dispozitiv (ENOSPC)"] --> CheckDF["Rulați: df -h ȘI df -i"]
CheckDF --> DiagType{"Ce raportează df?"}
DiagType -->|"df -h Afișează 100% Utilizare (0 Avail) ȘI df -i < 95%"| BlockFull["Epuizare bloc: Verificați dacă du -shx / Se potrivește cu df -h"]
DiagType -->|"df -h arată GB-uri gratuite, DAR df -i arată 100% IUse"| InodeFull["Epuizarea inodelor: milioane de fișiere minuscule de la 0 la 4KB"]
DiagType -->|"Atât df -h, cât și df -i arată < 90% Utilizat"| RamOrQuota["Limită ascunsă: verificați df -h /tmp (tmpfs RAM plină), Docker Overlay2 sau XFS/ext4 Disk Quotes"]
BlockFull --> GhostCheck{"Ați rulat deja rm pe fișiere mari fără să aruncați df?"}
GhostCheck -->|"Da: du este mult mai mic decât df"| UnlinkedFD["Rulați: sudo lsof +L1 -> Trunchiați fișierul fantomă prin: > /proc/PID/fd/FD"]
GhostCheck -->|"Nu: Fișierele reale umplu discul"| EmergencySpace["Creați o cameră de respirație imediată (1 GB până la 5 GB)"]
EmergencySpace --> Ext4Check{"Sistemul de fișiere este ext4 / ext3?"}
Ext4Check -->|"Da"| Tune2fs["Rulați: sudo tune2fs -m 1 /dev/root_dev (eliberează instantaneu 4% din disc pentru utilizatori non-root DB)"]
Ext4Check -->|"Nu (XFS / Btrfs / ZFS)"| TruncLogs["Trunchiați jurnalele în loc (: > /var/log/syslog) și rulați journalctl --vacuum-size=50M"]
InodeFull --> InodeClean["Găsiți directorul cu milioane de fișiere folosind find / -xdev -printf '%h\n' | sortare | uniq -c | sortare -k 1 -r | head -20 -> Delete cu find -delete"]
UnlinkedFD --> DBRecover["Treceți la Database Engine WAL și B-Tree Recovery"]
Tune2fs --> DBRecover
TruncLogs --> DBRecover
InodeClean --> DBRecover
RamOrQuota --> DBRecover
DBRecover --> WhichDB{"Ce motor de bază de date s-a prăbușit?"}
WhichDB -->|"PostgreSQL"| PGFlow["Păstrați pg_wal intact -> Porniți Postgres pentru a reda WAL -> Rulați CHECKPOINT; -> Eliminați sloturile de replicare învechite"]
WhichDB -->|"MySQL / MariaDB (InnoDB)"| MyFlow["Păstrați ib_logfile* intact -> Porniți mysqld -> Purgeți jurnalele binare prin PURGE BINARY LOGS -> Optimizați tabele"]
WhichDB -->|"SQLite3"| SqFlow["Backup .db + .db-wal + .db-shm -> Rulați PRAGMA wal_checkpoint(TRUNCATE) sau sqlite3 broken.db '.recover'"]
Faza 1: De ce comenzi standard (rm, apt, tab-completion) eșuează la 0 octeți liberi¶
Când o partiție Linux atinge blocarea de 100% sau epuizarea inodului, comenzile standard de remediere eșuează în moduri neașteptate:
- Apăsare Tab in bash aruncări cannot create temp file for here-document: No space left on device: Modern bash-completion scripturile creează fișiere temporare în /tmp. Dacă /tmp rezidă pe rădăcină / partiție în loc de a tmpfs Suport RAM, completare shell și heredocs (<<EOF) eșuează. Remediați acest lucru imediat arătând TMPDIR la memoria RAM partajată:
apt-get autoremove sau dpkg --configure -a eșuează cu No space left on device: Când /boot sau / este plin 100%, apt nu pot elimina nucleele vechi deoarece dpkg trebuie mai întâi să scrie actualizări de stare în /var/lib/dpkg/updates/. În schimb, fugi sudo apt-get clean (care se deconectează în cache .deb arhive în /var/cache/apt/archives/ direct), sau trunchiați o imagine de kernel neutilizată în /boot (sudo sh -c ': > /boot/initrd.img-<old-unused-version>') a da dpkg cei 50 de megaocteți (52,4 milioane de octeți) de care are nevoie pentru a rula sudo dpkg --purge linux-image-<old-unused-version>.
- rm /path/to/dir/* eșuează cu Argument list too long: Când df -i este la 100 la sută pentru că un director ca /var/lib/php/sessions conţine milioane de fişiere minuscule, metacaractere globbing (*) revarsă nucleul ARG_MAX tampon (2 megabytes) înainte rm începe. Utilizați find cu -delete in schimb:
Cele 5 cauze distincte ale No space left on device (ENOSPC)¶
Înainte de a atinge orice fișier de bază de date, comparați aceste cinci scenarii pentru a confirma ce resursă este de fapt epuizată:
| Comanda de diagnosticare | Simptomul observat | Cauza fundamentală | Remediere imediată în 10 secunde |
|---|---|---|---|
df -h vs sudo du -shx / |
df -h spectacole 100% folosit (0 Avail), dar du -shx / se adună numai la 60% de dimensiunea discului. |
Deschideți fișierele neconectate („Fișiere fantomă”): cineva a fugit rm pe un jurnal imens sau fișier temporar în timpul unui proces (nginx, java, postgres, docker) încă îl avea deschis. |
Fugi sudo lsof +L1, localizați PID şi FD al (deleted) fișier și rulați sudo sh -c ': > /proc/<PID>/fd/<FD>'. |
df -h spectacole 95% folosit, 0 Avail |
Used + Avail nu este egal Size; root pot scrie fișiere, dar postgres sau mysql devine ENOSPC. |
ext4 Blocuri rădăcină rezervate (5% implicit): ext4 reține 5% din blocuri de la utilizatorii non-root (UID > 0) pentru a preveni blocarea și fragmentarea rădăcinilor. |
Fugi sudo tune2fs -m 1 /dev/<partition> pentru a reduce rezerva de la 5% la 1% imediat online. |
df -i |
df -h arată gigaocteți de spațiu liber, dar df -i spectacole IUse% = 100% (IFree = 0). |
Epuizarea inodului: ext4 are un număr fix de inoduri create la mkfs timp; milioane de fișiere minuscule au consumat fiecare slot inod. |
Găsiți folderul vinovat (sudo find / -xdev -printf '%h\n' \ | sortare \ | uniq -c \ | sortare -k 1 -r \ | cap -10) and run sudo find /culprit/dir -type f -delete. |
sudo mount\ | grep /cale |
du -sh /var/log este mic, totuși / are 40 gigaocteți de spațiu lipsă. |
Fișiere ascunse sub un punct de montare: un proces a scris 40 de gigaocteți în /mnt/backup în timp ce unitatea externă a fost demontată, iar mai târziu cineva a montat un disc pe deasupra /mnt/backup, ascunzând fișierele subiacente de du. |
Montați sistemul de fișiere rădăcină într-o vizualizare temporară (sudo mkdir /dev/shm/rootview && sudo mount --bind / /dev/shm/rootview), verificați du -sh /dev/shm/rootview/mnt/*și ștergeți fișierele ascunse. |
btrfs filesystem df / |
df -h arată 20 de gigaocteți gratuit pe a Btrfs volum, dar scrierile eșuează cu ENOSPC. |
Btrfs Epuizarea blocurilor de metadate: Btrfs alocă spațiu în bucăți separate de date și metadate; dacă tot spațiul brut nealocat este blocat în bucăți rare de date, bucățile de metadate ajung la 100%. |
Adăugați temporar un dispozitiv cu buclă de fișiere RAM de 2 gigabyte (dd if=/dev/zero of=/dev/shm/btrfs_ram bs=1M count=2048 && sudo btrfs device add -f /dev/shm/btrfs_ram /), fugi sudo btrfs balance start -dusage=10 /, atunci sudo btrfs device remove /dev/shm/btrfs_ram /. |
Faza 2: Recuperarea spațiului pe disc în siguranță în mai puțin de 60 de secunde¶
Urmați acești pași exacti pentru a recupera între 500 de megaocteți și 50 de gigaocteți (0,53 miliarde până la 53,6 miliarde de octeți) de spațiu fără a corupe procesele active:
Pasul 1: trunchiați fișierele deschise șterse ("fantomă") prin /proc/<pid>/fd/¶
Dacă dvs. sau un script logrotate automat ați șters deja fișiere mari, dar spațiul pe disc nu a fost returnat, verificați tabelul de fișiere deschise deconectat de la kernel:
Uită-te laSIZE/OFF coloană (măsurată în octeți). Dacă vedeți o intrare ca:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
mysqld 1942 mysql 6u REG 259,1 34896609280 0 918273 /tmp/ibXz91aB (deleted)
rsyslogd 612 syslog 7w REG 259,1 18253611008 0 131092 /var/log/syslog.1 (deleted)
rsyslogd (PID 612, descriptor de fișier 7w -> 7) are deschis un fișier jurnal șters de 18,2 gigabyte. Nu kill -9 procesele bazei de date (mysqld sau postgres) a elibera /tmp fișiere dacă mai întâi puteți elibera spațiu în altă parte. În schimb, zero descriptorul fișierului jurnal (PID 612, FD 7) direct în memoria kernelului:
Fugi df -h imediat: toți cei 18,2 gigaocteți sunt eliberați pe loc fără a reporni un singur serviciu.
Pasul 2: Recuperați ext4 blocuri rezervate online cu tune2fs¶
Pe orice ext4 sau ext3 sistem de fișiere, verificați numărul curent de blocuri rezervate:
postgres), MySQL (mysql), Redis (redis), și aplicații web SQLite (www-data, node) rulează ca utilizatori non-root neprivilegiati, nucleul Linux îi împiedică să utilizeze ultimele 5 procente din disc. Scăderea raportului de blocare rezervat de la 5% la 1% (sau 0% în timpul unei urgențe active) are efect instantaneu pe un sistem de fișiere montat în direct:
Pe un volum de bază de date de 1 terabyte (1.000 de gigaocteți), această comandă unică predă imediat 40 de gigaocteți (42,9 miliarde de octeți) de spațiu de scris motorului dvs. de bază de date, astfel încât să își poată termina punctul de control WAL. Odată ce criza este rezolvată și datele vechi sunt curățate, restabiliți rezerva la 2% sau 5% (sudo tune2fs -m 2 /dev/nvme0n1p1).
Pasul 3: trunchiați jurnalele de text active în loc și aspirați journald¶
Găsiți cele mai mari fișiere din sistemul de fișiere rădăcină (rămânând pe același sistem de fișiere cu -xdev ca să nu pierzi timpul scanând /proc sau suporturi externe):
/var/log/nginx/access.log, /var/log/syslog, /var/log/postgresql/*.log, Docker *-json.log):
Nu fugi niciodată rm pe un fișier jurnal activ. Trunchiați-l la zero octeți în loc, astfel încât descriptorul de fișier al demonului să rămână valid și pointerii de compensare să se reseteze curat:
sudo truncate -s 0 /var/log/nginx/error.log
sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log
systemd-journald jurnalele binare (/var/log/journal/):
Faza 3: Recuperarea PostgreSQL după o blocare 100% disc plin (pg_wal balonare)¶
Când un server PostgreSQL rămâne fără spațiu pe disc, se înregistrează PANIC: could not write to file "pg_wal/xlogtemp.1234": No space left on device, anulează imediat procesele fii postmaster și refuză să pornească.
De ce pg_wal (pg_xlog în PostgreSQL 9.6 și mai vechi) umple întregul disc¶
În funcționare normală, PostgreSQL scrie fiecare modificare a fișierelor cu segmente de 16 megaocteți (16,7 milioane de octeți) în interior $PGDATA/pg_wal/ și le reciclează după fiecare CHECKPOINT odata ce depaseste max_wal_size. Cu toate acestea, PostgreSQL ** este interzis de la ștergerea sau reciclarea vechilor pg_wal fișiere** în trei condiții:
1. Un slot de replicare fizică/logică orfan sau întârziat: un server de replica (standby), conector Debezium/Kafka sau pg_receivewal clientul s-a deconectat cu câteva zile în urmă, dar slotul său de replicare (pg_replication_slots) este încă active = false pe primar, instruind PostgreSQL să păstreze fiecare segment WAL generat de la deconectare.
2. Un eșec archive_command: archive_mode = on este activat în postgresql.conf, și scriptul de rezervă (pgBackRest, WAL-G, Barman, sau aws s3 cp) returnează un cod de ieșire diferit de zero (de exemplu, o cheie S3 expirată sau o gazdă de rezervă inaccesibilă). PostgreSQL păstrează fiecare segment WAL nearhivat pg_wal/ până când archive_command se întoarce 0.
3. Un blocaj de disc plin: pg_wal a crescut până când 0 bytes rămas pe /var/lib/postgresql, iar acum PostgreSQL nici măcar nu poate începe să renunțe la slotul de replicare sau să finalizeze un punct de control, deoarece recuperarea la pornire în sine are nevoie de câțiva megaocteți de spațiu liber pe disc pentru a scrie fișiere de stare temporare.
Salvare în spațiu zero PostgreSQL pas cu pas (zero pierdere de date)¶
- Creează 1 gigabyte până la 5 gigaocteți (1,07 miliarde până la 5,36 miliarde de octeți) de spațiu temporar exterior
pg_wal/: - Prima utilizare
sudo tune2fs -m 0 /dev/<partition>și trunchiați jurnalele de text ale sistemului/PostgreSQL (sudo truncate -s 0 /var/lib/postgresql/*/main/log/*.logsau/var/log/postgresql/*.log). - ** Ce se întâmplă dacă baza de date are propria sa partiție dedicată cu zero jurnalele de text și XFS (deci
tune2fseste indisponibil)?** Mutați 10 în 20 dintre cel mai vechi.readysau fișiere inactive dintr-un director non-WAL sau relocațipg_waldirectorul temporar la o altă partiție cu spațiu liber folosind o legătură simbolică:# ONLY while PostgreSQL is completely stopped (verify with: ps aux | grep postgres) sudo mkdir -p /mnt/extra_space/pg_wal_rescue sudo chown -R postgres:postgres /mnt/extra_space/pg_wal_rescue sudo mv /var/lib/postgresql/16/main/pg_wal/* /mnt/extra_space/pg_wal_rescue/ sudo rmdir /var/lib/postgresql/16/main/pg_wal sudo ln -s /mnt/extra_space/pg_wal_rescue /var/lib/postgresql/16/main/pg_wal sudo chown -h postgres:postgres /var/lib/postgresql/16/main/pg_wal - Dacă
archive_commandeșuează și blochează reciclarea WAL, ocoliți-l temporarpostgresql.conf: Dacă ținta dvs. S3/backup este în jos șipg_wal/archive_status/conţine mii de.readyfișiere, editațipostgresql.conf(archive_command = '/bin/true') doar ca măsură de urgență de ultimă instanță pentru a împiedica moartea discului, știind că trebuie să luați o nouă măsurăpg_basebackupimediat după recuperare, deoarece lanțul de arhive WAL va avea un decalaj. - Porniți PostgreSQL și inspectați imediat sloturile de replicare:
Porniți PostgreSQL (
sudo systemctl start postgresql) și conectați-vă prinsudo -u postgres psql: - ** Eliminați orice slot de replicare mort/inactiv care acumulează gigaocteți de WAL**:
Dacă vedeți un slot inactiv (
active = f) deținând 80 gigaocteți deretained_wal: - Forțați imediat
CHECKPOINTpentru a recicla umflareapg_walsegmente: MomentulCHECKPOINT;se termină după eliminarea slotului mort, PostgreSQL va deconecta sau va recicla automat gigaocteți de fișiere de segment vechi de 16 megaocteți înpg_wal/, revenind la normal utilizarea discului. - Preveniți moartea discului slotului de replicare în viitor: Setați
max_slot_wal_keep_sizeinpostgresql.conf(disponibil în PostgreSQL 13+) la o limită sigură (cum ar fimax_slot_wal_keep_size = 20GB) deci PostgreSQL invalidează slotul unei replici moarte, în loc să blocheze baza de date primară la 0 octeți liberi.
Faza 4: Recuperarea MySQL / MariaDB (InnoDB) la 0 octeți liberi¶
Când accesează MySQL sau MariaDB 100% utilizarea discului (/var/lib/mysql), InnoDB blochează toate scrierile sau se blochează [ERROR] [MY-012640] [InnoDB] Error number 28 means 'No space left on device'.
Identificarea a ceea ce a umplut /var/lib/mysql¶
Fugi sudo du -sh /var/lib/mysql/* | sort -hr | head -n 15 pentru a vedea care dintre acești patru vinovați a consumat discul:
1. Jurnale binare nelimitate (binlog.000001, mysql-bin.000042): În mod implicit în MySQL 8.0+, înregistrarea binară este activată cu o reținere de 30 de zile (binlog_expire_logs_seconds = 2592000), care poate genera cu ușurință sute de gigaocteți de evenimente de rând în timpul importurilor în bloc.
2. O interogare care scrie tabele temporare gigantice (#sql* sau ibtmp1): Un masiv GROUP BY sau ORDER BY interogare completată ibtmp1 sau /tmp/#sql_* până când discul atinge 0 octeți.
3. Monolitic ibdata1 system tablespace bloat: Dacă innodb_file_per_table a fost dezactivată sau tranzacțiile de lungă durată au împiedicat lista istoricului InnoDB (anulați jurnalele din interior ibdata1 sau undo_001) din epurare.
4. ** Jurnal de interogări lente MySQL sau jurnal de erori (/var/log/mysql/mysql-slow.log)**.
Salvare pas cu pas MySQL / MariaDB zero-space¶
- ** NU ștergeți niciodată
ibdata1,ib_logfile0,ib_logfile1,#innodb_redo/*, sauundo_001curm**: Ștergerea oricăruia dintre aceste fișiere face ca fiecare.ibdFișierul tabel din baza de date nu poate fi citit. - Spațiu de pornire inițial gratuit (500 megaocteți până la 2 gigaocteți):
- Trunchiați
/var/log/mysql/error.logşimysql-slow.logviasudo truncate -s 0 /var/log/mysql/*.log. - Pornit
ext4, fugisudo tune2fs -m 1 /dev/<partition>. - Dacă
mysqldeste în prezent oprit şi/var/lib/mysql/ibtmp1(spațiul tabel temporar necomprimat) este imens,ibtmp1este recreat automat la pornire sau puteți muta cele mai vechi două sau trei jurnale binare (binlog.000001,binlog.000002- niciodată binlog activ cu cel mai mare număr) la/dev/shmtemporar asamysqldpoate porni. - Porniți MySQL și ștergeți în siguranță jurnalele binare folosind SQL (
PURGE BINARY LOGS)*: De ce trebuie să utilizați SQL în loc derm /var/lib/mysql/binlog.*? Deoarece MySQL urmărește fiecare nume de fișier de jurnal binar înbinlog.index. Dacă ștergeți jurnalele binare curmfara actualizarebinlog.index, MySQL va refuza pornirea sau replicarea se va întrerupe. Odatămysqldîncepe, conectați-vă (sudo mysql) și rulați: (Sau curățați totul până la fișierul jurnal activ curent afișat în partea de jos aSHOW BINARY LOGS;folosindPURGE BINARY LOGS TO 'binlog.000085';) - Setați o dimensiune permanentă a jurnalului binar și un plafon de retenție
/etc/mysql/mysql.conf.d/mysqld.cnf:Plafonare[mysqld] binlog_expire_logs_seconds = 259200 # Keep only 3 days (259,200 seconds) max_binlog_size = 256M innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:5Gibtmp1lamax:5Gasigură că un necinstit neindexatJOINsauORDER BYinterogarea eșuează cu atable is fulleroare în loc să se extindăibtmp1până când întregul server Linux moare la 0 octeți liberi.
Faza 5: Recuperarea unei baze de date SQLite3 corupte (database or disk is full / SQLITE_FULL / malformed)¶
Aplicații încorporate, containere Docker (Nextcloud, Vaultwarden, Home Assistant, Plex, Grafana, Gitea), iar serviciile mobile/desktop se bazează pe SQLite3. Când un disc atinge 0 octeți liberi în timp ce SQLite se află în mijlocul unui jurnal de derulare sau al unui jurnal de scriere anticipată (-wal) punct de control, veți întâlni una dintre cele două situații de urgență:
1. Masiv .db-wal dosar umflare (the .db-wal fișierul a crescut la 10 gigaocteți în timp ce fișierul .db fișierul are doar 200 de megaocteți, deoarece cititorii de lungă durată au împiedicat un punct de control WAL pasiv, iar acum discul este plin 100 la sută).
2. RuntimeError: database disk image is malformed (SQLITE_CORRUPT) cauzat de un hardware defect fsync(), un container a ucis la jumătatea derulării înapoi la 0 octeți liberi sau cineva care a șters -wal sau -journal dosar cu mana.
Warning
Nu mutați, redenumiți sau copiați niciodată a .db fișier de la sine în timp ce îl părăsiți .db-wal (Jurnal de scriere anticipată) sau .db-journal (Rollback Journal) dosar în spatele: Dacă app.db-wal sau app.db-journal există alături app.db, acel fișier însoțitor conține tranzacții angajate și pagini B-tree originale necesare pentru a fi efectuate app.db consistente structural. Copiați întotdeauna toate cele trei fișiere (app.db, app.db-wal, app.db-shm) împreună înainte de a rula orice comandă.
Pasul 1: micșorarea unui umflat .db-wal fișier și aspirarea SQLite atunci când spațiul pe disc este aproape de zero¶
- Opriți containerul aplicației sau serviciul care ține deschisă baza de date SQLite (
sudo systemctl stop appsaudocker stop container_name). - Copiere
app.db,app.db-wal, șiapp.db-shmpe o partiție sau o unitate externă cu mult spațiu liber (sau liber de două ori mai mare decâtapp.dbmai întâi pe discul local). - Deschide baza de date cu
sqlite3CLI și forțați un punct de control WAL trunchiat, care pliază toate cadrele comise dinapp.db-walînapp.dbsi se micsoreazaapp.db-walla 0 octeți: - Verificați integritatea structurală a arborelui B și a listei libere:
Dacă se imprimă
ok, baza de date este 100 la sută sănătoasă. - Cum să
VACUUMo bază de date SQLite uriașă când discul local nu are suficient spațiu liber: StandardVACUUM;necesită până la 2x dimensiunea bazei de date în spațiul liber pe disc pe aceeași partiție și/var/tmp. În schimb, foloseșteVACUUM INTO(introdus în SQLite 3.27.0) pentru a scrie o copie proaspăt compactată, defragmentată direct pe un disc montat separat sau pe o partajare de rețea:
Pasul 2: Salvarea unui arbore B corupt (database disk image is malformed) cu .recover¶
Dacă PRAGMA integrity_check; rapoarte row 412 missing from index, btreeInitPage() returns error code 11, sau database disk image is malformed:
- Încercați mai întâi să reconstruiți indecșii secundari deteriorați (
REINDEX)*: Adesea, datele reale din tabel (table B-trees) este 100 la sută intact și numai un arbore secundar al indexului B a fost corupt când discul sa umplut. Run:Dacăsqlite3 /mnt/external_usb/copy_of_app.db "REINDEX;" sqlite3 /mnt/external_usb/copy_of_app.db "PRAGMA integrity_check;"PRAGMA integrity_check;acum revineok, ați recuperat 100% din baza de date cu zero rânduri pierdute. - Dacă
REINDEXeșuează, rulați scanerul criminalistic B-tree (.recover)*: Spre deosebire de cei mai vechi.dumpcomandă (care oprește exportul unui tabel în momentul în care lovește un indicator B-tree corupt),.recover(încorporat însqlite3versiunea 3.29.0+) ocolește în întregime indicatorii din interiorul B-tree corupti, scanează fiecare pagină brută de 4 kiloocteți a fișierului secvenţial de la octetul 0 la EOF, reconstruiește fiecare rând care se poate citi și plasează orice înregistrări orfane într-unlost_and_foundtabel: - Verificați baza de date nou reconstruită:
Verificați dacă a
lost_and_founda fost creat tabelul (sqlite3 /mnt/external_usb/repaired_app.db ".tables") pentru a inspecta orice rânduri orfane recuperate din paginile de frunze nelegate. Pentru bazele de date criptate SQLCipher (cum ar fi copii de rezervă Signal sau WhatsApp), consultați ghidul nostru dedicat pe Coruperea copierii de rezervă a chat-ului SQLite, Signal și WhatsApp criptat și extragerea cheilor locale.
Faza 6: „Fișierul de balast Tripwire” de urgență și listă de verificare pentru prevenirea monitorizării¶
Odată ce serverul și baza de date sunt din nou online, implementați imediat aceste patru măsuri de siguranță, astfel încât să nu mai rămâneți niciodată prins la 0 octeți liberi:
- Creează un gigaoctet (
1,073,741,824octet) Fișier de balast de urgență pe fiecare partiție a bazei de date: Rulațisudo fallocate -l 1G /var/lib/EMERGENCY_DELETE_ME.ballast. Dacă serverul lovește vreodată100%disc plin, ruleazăsudo rm /var/lib/EMERGENCY_DELETE_ME.ballasteliberează 1 gigaoctet de blocuri învecinate într-o milisecundă. - Cap
systemd-journaldși jurnalele containerului Docker în mod permanent: SetațiSystemMaxUse=200Min/etc/systemd/journald.confși configurați/etc/docker/daemon.jsoncu"log-opts": {"max-size": "20m", "max-file": "3"}. - ** Izolați
/var/log,/tmp, și/var/lib/postgresqlpe volume LVM separate**: păstrare/var/logşi/tmpseparat de volumele bazei de date, se asigură că un jurnal web fugitiv nu blochează niciodată baza de date sau blochează conectările SSH. - Alerta pe AMBELE
df -h(> 80%) ȘIdf -i(> 80%) pluspg_replication_slotslag: Configurați monitorizarea (node_filesystem_avail_bytesşinode_filesystem_files_free) pentru a alerta înainte ca utilizarea să depășească 85 la sută.
Numerele regionale de urgență și protocoalele agenției¶
În timp ce un disc de server complet este, în mod normal, o urgență internă a operațiunilor IT, o întrerupere care afectează asistența medicală Electronic Health Record (EHR) baze de date, expediere de urgență (CAD), telemetria municipală pentru apă/energie electrică sau disponibilitatea legală a datelor cu caracter personal pot necesita o escaladare formală de urgență:
- Statele Unite și Canada: Apelați
911dacă o prăbușire a serverului dezactivează monitorizarea clinică sau expedierea și activează procedurile de nefuncționare. Raportați epuizarea resurselor de infrastructură critică sau atacurile ransomware către CISA (1-844-Say-CISA/cisa.gov/report) sau Centrul Canadian pentru Securitate Cibernetică (1-833-CYBER-88). - Regatul Unit: Apelați
999pentru amenințări la adresa vieții sau a sistemelor critice NHS. Conform Reglementărilor GDPR și NIS din Regatul Unit, evaluați dacă pierderea permanentă a disponibilității bazei de date necesită notificare către ICO (0303 123 1113) în 72 de ore. - Uniunea Europeană: Apelați
112în toate statele membre UE. Entitățile esențiale în conformitate cu Directiva NIS2 trebuie să își notifice CSIRT-ul național în termen de 24 de ore de la o întrerupere semnificativă, iar pierderea permanentă a datelor cu caracter personal fără recuperare de rezervă declanșează raportarea conform articolului 33 GDPR în 72 de ore. - Australia și Noua Zeelandă: Apelați
000în Australia sau111în Noua Zeelandă; contactați ACSC (1300 CYBER1) pentru incidente de infrastructură. - India și Asia-Pacific: Apelați
112pentru răspuns de urgență; raportați întreruperile induse de cibernetice către CERT-In (incident@cert-in.org.in) în intervalul obligatoriu de 6 ore.
Întrebări frecvente¶
De ce a făcut-o df -h rămâne la 100% (0 Avail) chiar și după ce am șters un fișier jurnal de 50 GB cu rm?¶
În sistemele de fișiere Linux, rm doar apeluri deconectați(), eliminând numele fișierului din director în timp ce nucleul păstrează blocurile de disc alocate până când fiecare proces care deține acel fișier deschis își închide descriptorul de fișier (i_count == 0). Fugi sudo lsof +L1 pentru a găsi ID-ul procesului (PID) și Descriptor de fișier (FD) din (șters) fișier, apoi rulați sudo sh -c ': > /proc/PID/fd/FD' pentru a zero blocurile în loc imediat fără a reporni serviciul.
Ce se întâmplă dacă nu pot nici măcar SSH pe server pentru că /tmp sau /var/run este plin 100% și sshd refuză să aloce o sesiune?¶
Mai întâi încercați să executați o comandă directă non-PTY prin SSH fără a aloca un pseudo-terminal interactiv: ssh -T root@server "sh -c ': > /var/log/syslog'". Dacă rădăcină autentificarea este dezactivată, utilizați consola serială out-of-band a furnizorului dvs. de cloud (AWS EC2 Serial Console, DigitalOcean Console, Linode Lish sau Proxmox/VMware VNC) pentru a vă conecta direct la ttyS0 sau porniți în modul de recuperare pentru un singur utilizator.
Cineva a șters deja fișierele din PostgreSQL pg_wal director înainte de a citi acest ghid, iar acum PostgreSQL refuză să înceapă cu PANIC: could not locate a valid checkpoint record. S-au pierdut toate datele?¶
Nu, majoritatea rândurilor de tabel sunt încă înăuntru $PGDATA/bază/, deși tranzacțiile în timpul zborului din fișierele WAL șterse se pierd și unele pagini pot fi rupte. Mai întâi faceți o copie completă a întregului $PGDATA director (cp -a /var/lib/postgresql/16/main /mnt/backup/pgdata_raw). Apoi fugi sudo -u postgres /usr/lib/postgresql/16/bin/pg_resetwal -f /var/lib/postgresql/16/main, porniți PostgreSQL în modul pentru utilizator unic și rulați imediat pg_dumpall într-un proaspăt inițializat (initdb) cluster; nu continuați niciodată să rulați trafic de producție pe un cluster după pg_resetwal.
Cum șterg milioane de fișiere mici când rm -rf se blochează sau se defectează de un inod epuizat (df -i 100%) server?¶
Când un director conține milioane de fișiere mici de sesiune sau cache, indexul directorului său (htree) crește uriaș, provocând ls şi rm -rf pentru a bloca sortarea numelor de fișiere în RAM. În schimb, fugi sudo find /path/to/million_files -mindepth 1 -deletesau creați un director RAM gol (mkdir /dev/shm/empty) și fugi sudo rsync -a --delete /dev/shm/empty/ /path/to/million_files/ pentru a deconecta rapid inodurile.
De ce mi-a umplut Docker întregul disc de server când containerele mele sunt mici și cum curăț /var/lib/docker în siguranță?¶
Docker acumulează spațiu pe disc în jurnalele JSON stdout nerotate (/var/lib/docker/containers/*/*-json.log), atârnând suprapunere2 straturi de imagine și memoria cache a kit-ului de construcție. Niciodată manual rm -rf dosare din interior /var/lib/docker/overlay2/. Mai întâi trunchiați jurnalele JSON (sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log) așa că demonul are spațiu de respirație, apoi fugi sudo docker system prune -a -f (omitând --volume astfel încât volumele bazei de date rămân neatinse).
Pot extinde un cloud EBS/volum de disc persistent în timp ce serverul este la 100% utilizare a discului?¶
Da, extinderea volumului online funcționează fără repornire, cu o singură captură: scriptul de ajutor growpart /dev/nvme0n1 1 încearcă să creeze un fișier temporar în /tmp folosind mktemp și eșuează la 0 octeți liberi. Ocoliți acel eșec rulând sudo TMPDIR=/dev/shm growpart /dev/nvme0n1 1 (folosind memoria RAM susținută /dev/shm monte) urmat de sudo resize2fs /dev/nvme0n1p1 (ext4) sau sudo xfs_growfs / (XFS).
Ghiduri aferente¶
rm -rfsauShift+Deleteaccidental pe Linux, macOS sau Windows: remontare imediată numai pentru citire- Coruperea copiei de rezervă a chat-ului SQLite, Signal și WhatsApp criptat și extragerea cheilor locale
- Fișier Word, Excel, PDF și baze de date corupte și recuperare documente nesalvate
- Modul de doar citire bruscă SSD și NVMe, blocuri de rezervă 0% și salvarea dezactivată TRIM
- Criză de găzduire web, migrare și restaurare de rezervă
- Numere de urgență în funcție de țară
Surse și îndrumări oficiale¶
- Grupul de dezvoltare globală PostgreSQL: Documentația oficială PostgreSQL 16 - Capitolul 30: Fiabilitate și jurnalul de scriere anticipată (Configurare WAL, Sloturi de replicare și Recuperare de la Eșecuri pline de disc).
- Consorțiul SQLite (
sqlite.org): Cum să corupți un fișier de bază de date SQLite (blocarea fișierelor, fișierele jurnal/WAL nelegate și.recoverExtensia CLI). - Oracle Corporation / Documentație MySQL și Fundația MariaDB: Recuperare în caz de accident InnoDB, proceduri de curățare a jurnalelor binare (
PURGE BINARY LOGS), și Spațiu tabel temporar (ibtmp1) Management. - Organizația Linux Kernel (
kernel.org): Administrarea sistemului de fișiere Ext4 (tune2fsBlocuri rezervate, tabele inode și/proc/<pid>/fd/Trunchierea descriptorului fișierului). - Institutul Național de Standarde și Tehnologie (
NIST) (Statele Unite ale Americii): Publicația specială 800-123: Ghid pentru securitatea generală a serverelor și managementul disponibilității.