Skip to content

Serverdisk 100 % full (0 byte ledig): Återställer en kraschad databas när rm och apt Underkänd på grund av brist på inoder/utrymme

Nödnummer skiljer sig åt mellan olika länder. Den här sidan använder 911, numret för USA och Kanada. Många andra länder använder 112, 999 eller ett annat nummer. Hitta numret för ditt land.

Upptäcker att en Linux-produktionsserver har träffat 100% diskanvändning (0 bytes free) eller 100% inodanvändning (df -i) medan du kör en aktiv PostgreSQL-, MySQL/InnoDB-, MariaDB- eller SQLite-databas är ett av de farligaste fellägena inom systemadministration. Vid noll byte eller noll fria inoder, kaskader krisen snabbt: operativsystemets kärna kan inte längre skapa Unix-domänsockets i /tmp eller /var/run, bash misslyckas med att tabb-komplettera eftersom det inte kan skriva tillfälliga skalpipor, apt eller dnf kan inte köra för att rensa upp paket eftersom pakethanterare kräver tillfälliga låsfiler och din databasmotor kraschar mitt i en Write-Ahead-logg (WAL) checkpoint eller vägrar att stänga av rent eftersom den inte kan tilldela ett enda 4 kilobyte (0,004 megabyte) block för sin .pid eller lås filen. Ännu värre är att panikslagna administratörer ofta kör rm -rf /var/log/*.log på multi-gigabyte loggfiler och titta i fasa som df -h rapporterar fortfarande 100% Use% (0 Avail), eller så raderas de dödligt pg_wal (pg_xlog) eller ib_logfile0 för att frigöra utrymme, permanent korrumperar databasen utöver transaktionsåterställning. Om du av misstag raderade viktiga databasfiler under ett rensningsförsök, sluta omedelbart och byt till oavsiktlig rm -rf eller Shift-Delete skrivskyddad återmontering och inodutskärning; om din underliggande lagringshårdvara ger I/O-fel eller har låst sig mot skrivningar, kontakta SSD och NVMe plötsligt skrivskyddat läge och TRIM inaktiverar räddning eller korrupt återställning av Word, Excel, PDF och databasfil. Om detta avbrott påverkar sjukhusets livsäkerhetssystem, akututskick eller kritiska allmännyttiga tjänster, ring ditt lokala nödnummer (911 i USA och Kanada, 112 över hela Europeiska unionen, 999 i Storbritannien) eller konsultera vår globala katalog över nödnummer.

Gör det här nu

  1. Radera INTE pg_wal/, pg_xlog/, pg_multixact/, ib_logfile*, undo_*, eller -wal / -shm filer för att skapa utrymme: Att radera Write-Ahead Log eller InnoDB gör om/ångra loggfiler medan en databas kraschar eller är okontrollerad förstör den enda posten av oengagerade sidor och sidor under flygning. En databas med en full disk är 100 procent återvinningsbar när utrymme är frigjort; en databas vars WAL-filer raderades manuellt med rm kommer att drabbas av irreversibel B-träd och hög korruption.
  2. ** Diagnostisera på 5 sekunder om du har slut på diskblock (df -h), utanför filsystemets inoder (df -i), eller håller öppna olänkade filer (lsof +L1)**:
  3. Kör df -h för att kontrollera blockkapacitet och df -i för att kontrollera inodens kapacitet. En server med 50 gigabyte (53,6 miljarder byte) ledigt diskutrymme kommer fortfarande att kasta No space left on device (ENOSPC) om df -i visar IUse% = 100% (orsakas vanligtvis av miljontals små sessions-, cache- eller e-postspoolfiler).
  4. Om df -h visar 100% används (0 Avail) även efter att du sprungit rm på stora loggfiler, kör sudo lsof +L1. Alla filer raderade med rm medan nginx, rsyslog, docker, postgres, eller mysqld har fortfarande en öppen filbeskrivning fortsätter att konsumera 100 procent av dess diskblock tills processen startar om eller du trunkerar deskriptorn direkt.
  5. Frigöra gigabyte utrymme på 1 sekund utan att starta om demoner genom att trunkera öppna filer på plats (: > /path/to/logfile eller : > /proc/<pid>/fd/<n>):
  6. Istället för rm /var/log/syslog (vilket lämnar block låsta av den körande loggern), nollställ filen på plats med hjälp av skal-null-omdirigeringen: sudo sh -c ': > /var/log/syslog' eller sudo truncate -s 0 /var/log/syslog.
  7. Om du redan sprungit rm på en massiv loggfil och df -h släppte inte, hitta dess process-ID (PID) och filbeskrivning (FD) in sudo lsof +L1 och trunkera det rakt genom kärnans procfs-gränssnitt: sudo sh -c ': > /proc/<PID>/fd/<FD>'. Space kommer att återvända till df -h omedelbart.
  8. Lås upp omedelbart andningsrum för nödläge ext4 / ext3 genom att sänka den reserverade rotblocksprocenten (tune2fs -m 1): Som standard, ext4 reserverar 5 procent av hela partitionen (25 gigabytes på en 500 gigabyte disk) exklusivt för UID 0 (root), vilket betyder icke-roottjänster som postgres (UID 109), mysql, och www-data träffa No space left on device vid 95 procents utnyttjande. Ta tillbaka 80 procent av denna reserv online på 1 sekund utan stilleståndstid genom att köra sudo tune2fs -m 1 /dev/sda1 (eller din rotblockeringsenhet från findmnt /).
  9. ** Vakuum systemd-journald binära loggar och gamla paketcacher säkert**: Kör sudo journalctl --vacuum-size=50M (som säkert roterar och rensar binärt /var/log/journal arkiv ner till 50 megabyte) och sudo apt-get clean (eller sudo dnf clean all), som tar bort nedladdade .deb / .rpm arkiverar i /var/cache/apt/archives/ utan att behöva skriva till dpkg-databasen.
  10. När minst 1 gigabyte till 5 gigabyte (1,07 miljarder till 5,36 miljarder byte) utrymme är ledigt, ta upp databasen i enanvändar- eller återställningsläge för att slutföra sin WAL-kontrollpunkt innan klienttrafik tillåts: Låt PostgreSQL, MySQL/InnoDB eller SQLite spela upp sin Write-Ahead-logg igen (WAL), spola smutsiga sidor till huvuddatafilerna och återvinn dess uppsvällda WAL-segment rent innan du öppnar din programbrandvägg eller webbserver igen.

Danger

** Spring aldrig pg_resetwal (eller pg_resetxlog) på PostgreSQL eller innodb_force_recovery = 6 på MySQL helt enkelt för att disken fylldes upp**: Körs pg_resetwal torkar transaktionsloggpekarna och tvingar PostgreSQL att börja med halvskrivna datasidor, vilket garanterar tyst radförlust, dubbletter av primärnycklar och trasiga B-träd med främmande nyckel. I 99,9 procent av diskfulla databaskrascher, helt enkelt frigöring av 2 gigabyte till 10 gigabyte (2,1 miljarder till 10,7 miljarder byte) utrymme på partitionen och start av databasdemonen tillåter normalt automatisk kraschåterställning (REDO fas) för att avsluta rent med noll dataförlust.


Beslutsträd: nollutrymmesserver och kraschad databastriage

Använd detta beslutsträd för att identifiera varför operativsystemet rapporterar ENOSPC (No space left on device) och välj den exakta oförstörande återställningsvägen:

flowchart TD
    Start["Server- eller databaskastning: Inget utrymme kvar på enheten (ENOSPC)"] --> CheckDF["Kör: df -h OCH df -i"]

    CheckDF --> DiagType{"Vad rapporterar df?"}

    DiagType -->|"df -h visar 100 % användning (0 tillgänglighet) OCH df -i < 95 %"| BlockFull["Block Exhaustion: Kontrollera om du -shx / Matchar df -h"]
    DiagType -->|"df -h visar gratis GBs MEN df -i visar 100 % IUse"| InodeFull["Inodutmattning: Miljontals små 0-till-4KB-filer"]
    DiagType -->|"Både df -h och df -i Visa < 90 % använd"| RamOrQuota["Dold gräns: Kontrollera df -h /tmp (tmpfs RAM fullt), Docker Overlay2 eller XFS/ext4 diskkvoter"]

    BlockFull --> GhostCheck{"Körde du redan rm på stora filer utan att df släpper?"}
    GhostCheck -->|"Ja: du är mycket mindre än df"| UnlinkedFD["Kör: sudo lsof +L1 -> Truncate Ghost File via: > /proc/PID/fd/FD"]
    GhostCheck -->|"Nej: riktiga filer fylls på disken"| EmergencySpace["Skapa omedelbart andningsrum (1 GB till 5 GB)"]

    EmergencySpace --> Ext4Check{"Är filsystemet ext4 / ext3?"}
    Ext4Check -->|"Ja"| Tune2fs["Kör: sudo tune2fs -m 1 /dev/root_dev (frigör omedelbart 4 % av disken för icke-root-DB-användare)"]
    Ext4Check -->|"Nej (XFS / Btrfs / ZFS)"| TruncLogs["Trunkera loggar på plats (: > /var/log/syslog) och kör journalctl --vacuum-size=50M"]

    InodeFull --> InodeClean["Hitta katalog med miljontals filer med find / -xdev -printf '%h\n' | sortera | uniq -c | sortera -k 1 -r | huvud -20 -> Ta bort med hitta -radera"]

    UnlinkedFD --> DBRecover["Fortsätt till Database Engine WAL & B-Tree Recovery"]
    Tune2fs --> DBRecover
    TruncLogs --> DBRecover
    InodeClean --> DBRecover
    RamOrQuota --> DBRecover

    DBRecover --> WhichDB{"Vilken databasmotor kraschade?"}
    WhichDB -->|"PostgreSQL"| PGFlow["Håll pg_wal intakt -> Starta Postgres för att spela om WAL -> Kör CHECKPOINT; -> Släpp inaktuella replikeringsplatser"]
    WhichDB -->|"MySQL / MariaDB (InnoDB)"| MyFlow["Behåll ib_logfile* Intakt -> Starta mysqld -> Rensa binära loggar via PURGE BINARY LOGS -> Optimera tabeller"]
    WhichDB -->|"SQLite3"| SqFlow["Säkerhetskopiera .db + .db-wal + .db-shm -> Kör PRAGMA wal_checkpoint(TRUNCATE) eller sqlite3 broken.db '.recover'"]

Fas 1: Varför standardkommandon (rm, apt, tab-completion) misslyckas vid 0 byte gratis

När en Linux-partition når 100 procent block- eller inodutmattning, misslyckas vanliga korrigeringskommandon på oväntade sätt: - Tryckande Tab in bash kastar cannot create temp file for here-document: No space left on device: Modernt bash-completion skript skapar temporära filer i /tmp. Om /tmp ligger på roten / partition istället för en tmpfs RAM-fäste, skalkomplettering och heredocs (<<EOF) misslyckas. Fixa detta omedelbart genom att peka TMPDIR till delat minne RAM:

export TMPDIR=/dev/shm
- apt-get autoremove eller dpkg --configure -a misslyckas med No space left on device: När /boot eller / är 100 procent full, apt kan inte ta bort gamla kärnor pga dpkg måste först skriva statusuppdateringar i /var/lib/dpkg/updates/. Spring istället sudo apt-get clean (som tar bort länkar cachad .deb arkiverar i /var/cache/apt/archives/ direkt), eller trunkera en oanvänd kärnbild i /boot (sudo sh -c ': > /boot/initrd.img-<old-unused-version>') att ge dpkg de 50 megabyte (52,4 miljoner byte) som den behöver för att köras sudo dpkg --purge linux-image-<old-unused-version>. - rm /path/to/dir/* misslyckas med Argument list too long: När df -i är på 100 procent eftersom en katalog som /var/lib/php/sessions innehåller miljontals små filer, jokertecken globbing (*) svämmar över kärnan ARG_MAX buffert (2 megabytes) innan rm startar. Använd find med -delete istället:
sudo find /var/lib/php/sessions -type f -delete

De 5 distinkta orsakerna till No space left on device (ENOSPC)

Innan du rör några databasfiler, jämför dessa fem scenarier för att bekräfta vilken resurs som faktiskt är uttömd:

Diagnostiskt kommando Symtom observerat Rotorsak Omedelbar 10-sekunders fix
df -h vs sudo du -shx / df -h visar 100% används (0 Avail), men du -shx / läggs till endast 60% av diskstorleken. Öppna olänkade filer ("Ghost Files"): Någon sprang rm på en enorm logg eller temporär fil under en process (nginx, java, postgres, docker) hade den fortfarande öppen. Kör sudo lsof +L1, lokalisera PID och FD av (deleted) fil och kör sudo sh -c ': > /proc/<PID>/fd/<FD>'.
df -h visar 95% används, 0 Avail Used + Avail är inte lika Size; root kan skriva filer, men postgres eller mysql får ENOSPC. ext4 Reserverade rotblock (5 % standard): ext4 undanhåller 5 procent av blockeringarna från icke-rootanvändare (UID > 0) för att förhindra rotlåsning och fragmentering. Kör sudo tune2fs -m 1 /dev/<partition> att sänka reserven från 5 procent till 1 procent direkt online.
df -i df -h visar gigabyte ledigt utrymme, men df -i visar IUse% = 100% (IFree = 0). Inodutmattning: ext4 har ett fast antal inoder skapade vid mkfs tid; miljontals små filer konsumerade varje inodplats. Hitta den skyldige mappen (sudo find / -xdev -printf '%h\n' \ | sortera \ | uniq -c \ | sortera -k 1 -r \ | huvud -10) and run sudo hitta /culprit/dir -typ f -delete.
sudo mount \ | grep /sökväg du -sh /var/log är liten, ändå / har 40 gigabyte saknat utrymme. Gömda filer under en monteringspunkt: En process skrev in 40 gigabyte /mnt/backup medan den externa enheten var avmonterad, och senare monterade någon en disk ovanpå /mnt/backup, döljer de underliggande filerna från du. Bind-montera rotfilsystemet till en tillfällig vy (sudo mkdir /dev/shm/rootview && sudo mount --bind / /dev/shm/rootview), kontrollera du -sh /dev/shm/rootview/mnt/*och radera de dolda filerna.
btrfs filesystem df / df -h visar 20 gigabyte gratis på en Btrfs volym, men skriver misslyckas med ENOSPC. Btrfs Metadata Chunk Exhaustion: Btrfs fördelar utrymme i separata data- och metadatabitar; om allt oallokerat råutrymme är låst till glesa databitar, träffar Metadata-bitar 100 procent. Lägg tillfälligt till en 2 gigabyte RAM-filloopenhet (dd if=/dev/zero of=/dev/shm/btrfs_ram bs=1M count=2048 && sudo btrfs device add -f /dev/shm/btrfs_ram /), springa sudo btrfs balance start -dusage=10 /, då sudo btrfs device remove /dev/shm/btrfs_ram /.

Fas 2: Återta diskutrymme säkert på under 60 sekunder

Följ dessa exakta steg för att återta mellan 500 megabyte och 50 gigabyte (0,53 miljarder till 53,6 miljarder byte) utrymme utan att korrumpera aktiva processer:

Steg 1: Trunkera öppna raderade ("spöke") filer via /proc/<pid>/fd/

Om du eller ett automatiserat logrotate-skript redan har tagit bort stora filer men diskutrymme inte har returnerats, kontrollera kärnans olänkade öppna filtabell:

sudo lsof +L1
Titta på SIZE/OFF kolumn (mätt i byte). Om du ser en post som:
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)
Här, rsyslogd (PID 612, filbeskrivning 7w -> 7) håller en 18,2 gigabyte raderad loggfil öppen. Gör inte det kill -9 databasprocesser (mysqld eller postgres) för att frigöra /tmp filer om du kan frigöra utrymme någon annanstans först. Nollställ istället loggfilsbeskrivningen (PID 612, FD 7) direkt i kärnminnet:
sudo sh -c ': > /proc/612/fd/7'
Kör df -h omedelbart: alla 18,2 gigabyte frigörs på plats utan att starta om en enda tjänst.

Steg 2: Återta ext4 reserverade block online med tune2fs

På vilken som helst ext4 eller ext3 filsystem, kontrollera det aktuella antalet reserverade block:

df -h /
sudo tune2fs -l /dev/nvme0n1p1 | grep -i "reserved block"
Eftersom PostgreSQL (postgres), MySQL (mysql), Redis (redis), och SQLite webbappar (www-data, node) körs som oprivilegierade icke-rootanvändare, blockerar Linux-kärnan dem från att använda de sista 5 procenten av disken. Sänka det reserverade blockförhållandet från 5% till 1% (eller 0% under en aktiv nödsituation) träder i kraft omedelbart på ett livemonterat filsystem:
sudo tune2fs -m 1 /dev/nvme0n1p1
På en 1 terabyte (1 000 gigabyte) databasvolym lämnar detta enda kommando omedelbart 40 gigabyte (42,9 miljarder byte) skrivbart utrymme till din databasmotor så att den kan avsluta sin WAL-kontrollpunkt. När krisen är löst och gammal data rensats, återställ reserven till 2% eller 5% (sudo tune2fs -m 2 /dev/nvme0n1p1).

Steg 3: Trunkera aktiva textloggar på plats och dammsug journald

Hitta de största filerna i rotfilsystemet (förblir på samma filsystem som -xdev så att du inte slösar tid på att skanna /proc eller externa fästen):

sudo find / -xdev -type f -size +100M -exec ls -lh {} + 2>/dev/null | sort -k 5 -hr | head -n 25
- För stora loggfiler i vanlig text (/var/log/nginx/access.log, /var/log/syslog, /var/log/postgresql/*.log, hamnarbetare *-json.log): Spring aldrig rm på en aktiv loggfil. Trunkera den till noll byte på plats så att demonens filbeskrivning förblir giltig och offsetpekare återställs rent:
sudo truncate -s 0 /var/log/nginx/error.log
sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log
- För systemd-journald binära loggar (/var/log/journal/):
sudo journalctl --vacuum-size=50M


Fas 3: Återställer PostgreSQL efter en 100% diskfull krasch (pg_wal uppblåsthet)

När en PostgreSQL-server får slut på diskutrymme loggas den PANIC: could not write to file "pg_wal/xlogtemp.1234": No space left on device, avbryter omedelbart postmästarens barnprocesser och vägrar starta.

Varför pg_wal (pg_xlog i PostgreSQL 9.6 och äldre) fyller hela disken

I normal drift skriver PostgreSQL varje ändring till 16 megabyte (16,7 miljoner byte) segmentfiler inuti $PGDATA/pg_wal/ och återvinner dem efter varje CHECKPOINT en gång överskrider max_wal_size. Det är dock förbjudet för PostgreSQL ** att radera eller återvinna gamla pg_wal filer** under tre villkor: 1. En föräldralös eller eftersläpande fysisk/logisk replikeringsplats: En replikserver (standby), Debezium/Kafka-kontakt, eller pg_receivewal klient kopplades bort för några dagar sedan, men dess replikeringsplats (pg_replication_slots) är stilla active = false på den primära, instruerar PostgreSQL att behålla varje enskilt WAL-segment som genererats sedan frånkopplingen. 2. Ett misslyckande archive_command: archive_mode = on är aktiverat i postgresql.conf, och säkerhetskopieringsskriptet (pgBackRest, WAL-G, Barman, eller aws s3 cp) returnerar en utgångskod som inte är noll (till exempel en utgången S3-nyckel eller oåtkomlig backup-värd). PostgreSQL håller alla oarkiverade WAL-segment inne pg_wal/ tills archive_command returnerar 0. 3. Ett diskfullt dödläge: pg_wal växte fram till 0 bytes stannade kvar /var/lib/postgresql, och nu kan PostgreSQL inte ens börja tappa replikeringsplatsen eller slutföra en kontrollpunkt eftersom startåterställning i sig behöver flera megabyte ledigt diskutrymme för att skriva temporära tillståndsfiler.

Steg-för-steg PostgreSQL nollutrymmesräddning (noll dataförlust)

  1. Skapa 1 gigabyte till 5 gigabyte (1,07 miljarder till 5,36 miljarder byte) tillfälligt utrymme utanför pg_wal/:
  2. Första användning sudo tune2fs -m 0 /dev/<partition> och trunkera system/PostgreSQL-textloggar (sudo truncate -s 0 /var/lib/postgresql/*/main/log/*.log eller /var/log/postgresql/*.log).
  3. Tänk om databasen har en egen dedikerad partition med noll textloggar och XFS (så tune2fs är inte tillgänglig)? Flytta 10 till 20 av de äldsta .ready eller inaktiva filer från en icke-WAL-katalog, eller flytta pg_wal katalog tillfälligt till en annan partition med ledigt utrymme med hjälp av en symbolisk länk:
    # 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
    
  4. Om archive_command misslyckas och blockerar WAL-återvinning, förbigå den tillfälligt postgresql.conf: Om ditt S3/backup-mål är nere och pg_wal/archive_status/ innehåller tusentals .ready filer, redigera postgresql.conf (archive_command = '/bin/true') endast som en sista utväg för att förhindra att skivan dör, med vetskap om att du måste ta en ny pg_basebackup omedelbart efter återhämtning eftersom WAL-arkivkedjan kommer att ha en lucka.
  5. Starta PostgreSQL och inspektera omedelbart replikeringsplatser: Starta PostgreSQL (sudo systemctl start postgresql) och anslut via sudo -u postgres psql:
    SELECT slot_name, plugin, slot_type, active,
           pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal
    FROM pg_replication_slots;
    
  6. Släpp alla döda/inaktiva replikeringsplatser som lagrar gigabyte WAL: Om du ser en inaktiv plats (active = f) rymmer 80 gigabyte retained_wal:
    SELECT pg_drop_replication_slot('name_of_dead_slot');
    
  7. Tvinga fram en omedelbar CHECKPOINT att återvinna det uppsvällda pg_wal segment:
    CHECKPOINT;
    
    Ögonblicket CHECKPOINT; avslutas efter att den döda platsen har tappats, kommer PostgreSQL automatiskt att ta bort länken eller återvinna gigabyte av gamla 16 megabyte segmentfiler i pg_wal/, återställer din diskanvändning till det normala.
  8. Förhindra framtida replikeringsplatsdiskdöd: Ställ in max_slot_wal_keep_size in postgresql.conf (tillgänglig i PostgreSQL 13+) till ett säkert lock (som t.ex max_slot_wal_keep_size = 20GB) så PostgreSQL ogiltigförklarar en död replikas plats istället för att krascha den primära databasen med 0 byte ledig.

Fas 4: Återställa MySQL / MariaDB (InnoDB) vid 0 byte ledig

När MySQL eller MariaDB träffar 100% diskanvändning (/var/lib/mysql), InnoDB stoppar alla skrivningar eller kraschar med [ERROR] [MY-012640] [InnoDB] Error number 28 means 'No space left on device'.

Identifiera vad som fyllde /var/lib/mysql

Kör sudo du -sh /var/lib/mysql/* | sort -hr | head -n 15 för att se vilka av dessa fyra skyldiga som konsumerade skivan: 1. Obundna binära loggar (binlog.000001, mysql-bin.000042): Som standard i MySQL 8.0+ är binär loggning aktiverad med en 30-dagars retention (binlog_expire_logs_seconds = 2592000), som enkelt kan generera hundratals gigabyte radhändelser under massimporter. 2. En skenande fråga som skriver gigantiska tillfälliga tabeller (#sql* eller ibtmp1): En massiv GROUP BY eller ORDER BY fråga fylld ibtmp1 eller /tmp/#sql_* tills disken träffade 0 byte. 3. ** Monolitisk ibdata1 system tablespace bloat**: Om innodb_file_per_table inaktiverades eller långvariga transaktioner förhindrade InnoDB-historiklistan (ångra loggar inuti ibdata1 eller undo_001) från rensning. 4. MySQL långsam frågelogg eller fellogg (/var/log/mysql/mysql-slow.log).

Steg-för-steg MySQL / MariaDB noll-utrymme räddning

  1. Radera ALDRIG ibdata1, ib_logfile0, ib_logfile1, #innodb_redo/*, eller undo_001 med rm: Om du tar bort någon av dessa filer blir varje .ibd tabellfilen i din databas oläsbar.
  2. Fritt utrymme för första start (500 megabyte till 2 gigabyte):
  3. Trunkera /var/log/mysql/error.log och mysql-slow.log via sudo truncate -s 0 /var/log/mysql/*.log.
  4. På ext4, springa sudo tune2fs -m 1 /dev/<partition>.
  5. Om mysqld är för närvarande stoppad och /var/lib/mysql/ibtmp1 (den icke-komprimerade temporära tabellytan) är enorm, ibtmp1 återskapas automatiskt vid start, eller så kan du flytta de äldsta två eller tre binära loggarna (binlog.000001, binlog.000002 - aldrig den högst numrerade aktiva binloggen) till /dev/shm tillfälligt så mysqld kan starta.
  6. Starta MySQL och rensa binära loggar säkert med SQL (PURGE BINARY LOGS): Varför måste du använda SQL istället för rm /var/lib/mysql/binlog.*? Eftersom MySQL spårar alla binära loggfilnamn i binlog.index. Om du tar bort binära loggar med rm utan uppdatering binlog.index, kommer MySQL att vägra starta eller replikeringen kommer att gå sönder. En gång mysqld startar, logga in (sudo mysql) och kör:
    SHOW BINARY LOGS;
    PURGE BINARY LOGS BEFORE NOW() - INTERVAL 1 DAY;
    
    (Eller rensa allt upp till den aktuella aktiva loggfilen som visas längst ned i SHOW BINARY LOGS; använder PURGE BINARY LOGS TO 'binlog.000085';)
  7. Sätt in en permanent binär loggstorlek och kvarhållningslock /etc/mysql/mysql.conf.d/mysqld.cnf:
    [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:5G
    
    Övertäckning ibtmp1 kl max:5G säkerställer att en skurk oindexeras JOIN eller ORDER BY fråga misslyckas med en table is full fel istället för att expandera ibtmp1 tills hela Linux-servern dör vid 0 byte ledig.

Fas 5: Återställa en skadad SQLite3-databas (database or disk is full / SQLITE_FULL / malformed)

Inbäddade applikationer, Docker-behållare (Nextcloud, Vaultwarden, Home Assistant, Plex, Grafana, Gitea), och mobila/datortjänster förlitar sig på SQLite3. När en disk når 0 byte ledig medan SQLite är mitt i en journalåterställning eller en Write-Ahead-logg (-wal) checkpoint kommer du att stöta på en av två nödsituationer: 1. Massiv .db-wal file bloat (den .db-wal filen har vuxit till 10 gigabyte medan .db filen är bara 200 megabyte, eftersom långvariga läsare förhindrade en passiv WAL-kontrollpunkt, och nu är disken 100 procent full). 2. RuntimeError: database disk image is malformed (SQLITE_CORRUPT) orsakad av en trasig hårdvara fsync(), en behållare dödad mitt i rollback med 0 byte ledig, eller någon som tar bort -wal eller -journal fil för hand.

Warning

Flytta aldrig, byt namn på eller kopiera aldrig en .db fil själv medan du lämnar den .db-wal (Write-Ahead Log) eller .db-journal (Rollback Journal) fil bakom: If app.db-wal eller app.db-journal finns vid sidan av app.db, den följefilen innehåller genomförda transaktioner och ursprungliga B-trädsidor som krävs för att göra app.db strukturellt konsekvent. Kopiera alltid alla tre filerna (app.db, app.db-wal, app.db-shm) tillsammans innan du kör något kommando.

Steg 1: Krympa en uppsvälld .db-wal fil och dammsuger SQLite när diskutrymmet är nära noll

  1. Stoppa applikationsbehållaren eller tjänsten som håller SQLite-databasen öppen (sudo systemctl stop app eller docker stop container_name).
  2. Kopiera app.db, app.db-wal, och app.db-shm till en partition eller extern enhet med gott om ledigt utrymme (eller ledigt 2x storleken på app.db på den lokala disken först).
  3. Öppna databasen med sqlite3 CLI och tvinga fram en trunkerande WAL-kontrollpunkt, som viker alla engagerade ramar från app.db-wal in i app.db och krymper app.db-wal till 0 byte:
    sqlite3 /path/to/app.db "PRAGMA wal_checkpoint(TRUNCATE);"
    
  4. Verifiera B-trädets och frilistans strukturella integritet:
    sqlite3 /path/to/app.db "PRAGMA integrity_check;"
    
    Om det skrivs ut ok, är din databas 100 procent frisk.
  5. ** Hur man VACUUM en enorm SQLite-databas när den lokala disken inte har tillräckligt med ledigt utrymme**: Standard VACUUM; kräver upp till 2x databasstorleken i ledigt diskutrymme på samma partition och /var/tmp. Använd istället VACUUM INTO (introducerat i SQLite 3.27.0) för att skriva en nykomprimerad, defragmenterad kopia direkt till en separat monterad disk eller nätverksresurs:
    sqlite3 /path/to/app.db "VACUUM INTO '/mnt/external_usb/app_compacted.db';"
    

Steg 2: Rädda ett skadat B-träd (database disk image is malformed) med .recover

Om PRAGMA integrity_check; rapporterar row 412 missing from index, btreeInitPage() returns error code 11, eller database disk image is malformed:

  1. Försök först att bygga om trasiga sekundära index (REINDEX): Ofta de faktiska tabelldata (table B-trees) är 100 procent intakt och endast ett sekundärt index B-träd skadades när disken fylldes. Kör:
    sqlite3 /mnt/external_usb/copy_of_app.db "REINDEX;"
    sqlite3 /mnt/external_usb/copy_of_app.db "PRAGMA integrity_check;"
    
    Om PRAGMA integrity_check; återkommer nu ok, har du återställt 100 procent av din databas med noll förlorade rader.
  2. Om REINDEX misslyckas, kör den rättsmedicinska B-tree scanner (.recover): Till skillnad från den äldre .dump kommando (som slutar exportera en tabell i samma ögonblick som den träffar en skadad B-trädpekare), .recover (inbyggd sqlite3 version 3.29.0+) förbigår de skadade inre B-trädpekarna helt, skannar varje obearbetad 4 kilobyte bladsida i filen sekventiellt från byte 0 till EOF, rekonstruerar varje läsbar rad och placerar alla föräldralösa poster i en lost_and_found tabell:
    sqlite3 /mnt/external_usb/copy_of_app.db ".recover" | sqlite3 /mnt/external_usb/repaired_app.db
    
  3. Verifiera den nyrekonstruerade databasen:
    sqlite3 /mnt/external_usb/repaired_app.db "PRAGMA integrity_check;"
    
    Kontrollera om a lost_and_found tabellen skapades (sqlite3 /mnt/external_usb/repaired_app.db ".tables") för att inspektera eventuella föräldralösa rader som återställts från olänkade bladsidor. För krypterade SQLCipher-databaser (som Signal- eller WhatsApp-säkerhetskopior), se vår dedikerade guide om krypterad SQLite, Signal och WhatsApp chat backup korruption och lokal nyckelextraktion.

Fas 6: Nödsituation "Tripwire Ballast File" & checklista för förebyggande av övervakning

När din server och databas är online igen, implementera dessa fyra skyddsåtgärder omedelbart så att du aldrig är fången på 0 byte ledig igen:

  • Skapa en 1 gigabyte (1,073,741,824 byte) Emergency Ballast File på varje databaspartition: Kör sudo fallocate -l 1G /var/lib/EMERGENCY_DELETE_ME.ballast. Om servern någonsin träffar 100% disken full, igång sudo rm /var/lib/EMERGENCY_DELETE_ME.ballast frigör 1 gigabyte av sammanhängande block på 1 millisekund.
  • Cap systemd-journald och Docker-containerloggar permanent: Ställ in SystemMaxUse=200M in /etc/systemd/journald.conf och konfigurera /etc/docker/daemon.json med "log-opts": {"max-size": "20m", "max-file": "3"}.
  • Isolera /var/log, /tmp, och /var/lib/postgresql på separata LVM-volymer: Behåller /var/log och /tmp separat från databasvolymer säkerställer att en skenande webblogg aldrig kraschar databasen eller låser ute SSH-inloggningar.
  • Varning på BÅDA df -h (> 80%) OCH df -i (> 80%) plus pg_replication_slots fördröjning: Konfigurera övervakning (node_filesystem_avail_bytes och node_filesystem_files_free) för att varna innan användningen passerar 85 procent.

Regionala nödnummer och byråprotokoll

Medan en full serverdisk normalt är en intern IT-driftsnödsituation, påverkar ett avbrott sjukvårdens elektroniska hälsojournal (EHR) databaser, nödsändning (CAD), kommunal vatten-/krafttelemetri eller lagstadgad tillgång till personuppgifter kan kräva en formell nödupptrappning:

  • USA och Kanada: Slå 911 om en serverkrasch inaktiverar klinisk övervakning eller sändning och aktiverar driftstopp. Rapportera resursutmattning av kritisk infrastruktur eller ransomware-attacker till CISA (1-844-Say-CISA / cisa.gov/report) eller Canadian Center for Cyber Security (1-833-CYBER-88).
  • Storbritannien: Ring 999 för hot mot liv eller kritiska NHS-system. Under brittiska GDPR och NIS-förordningar, bedöm om permanent databastillgänglighetsförlust kräver meddelande till ICO (0303 123 1113) inom 72 timmar.
  • Europeiska unionen: Ring 112 i alla EU:s medlemsländer. Viktiga enheter enligt NIS2-direktivet måste meddela sin nationella CSIRT inom 24 timmar om ett betydande avbrott, och permanent förlust av personuppgifter utan säkerhetskopiering utlöser rapportering enligt GDPR Artikel 33 inom 72 timmar.
  • Australien och Nya Zeeland: Ring 000 i Australien eller 111 i Nya Zeeland; kontakta ACSC (1300 CYBER1) för infrastrukturincidenter.
  • Indien och Asien-Stillahavsområdet: Ring 112 för nödsituationer; rapportera cyberinducerade avbrott till CERT-In (incident@cert-in.org.in) inom det obligatoriska 6-timmarsfönstret.

Vanliga frågor

Varför gjorde det df -h stanna på 100 % (0 Avail) även efter att jag tagit bort en 50 GB loggfil med rm?

I Linux-filsystem, rm bara samtal ta bort länk (), tar bort filnamnet från katalogen medan kärnan behåller diskblocken tilldelade tills varje process som håller den filen öppen stänger dess filbeskrivning (i_count == 0). Kör sudo lsof +L1 för att hitta process-ID (PID) och filbeskrivning (FD) av (raderad) fil och kör sedan sudo sh -c ': > /proc/PID/fd/FD' att nollställa blocken på plats omedelbart utan att starta om tjänsten.

Tänk om jag inte ens kan SSH till servern pga /tmp eller /var/run är 100% full och sshd vägrar att tilldela en session?

Försök först att köra ett icke-PTY direkt kommando över SSH utan att allokera en interaktiv pseudoterminal: ssh -T root@server "sh -c ': > /var/log/syslog'". Om rot inloggning är inaktiverad, använd din molnleverantörs out-of-band seriella konsol (AWS EC2 Serial Console, DigitalOcean Console, Linode Lish eller Proxmox/VMware VNC) för att logga in direkt på ttyS0 eller starta i återställningsläge för en användare.

Någon har redan tagit bort filer i PostgreSQL:s pg_wal katalog innan du läser den här guiden, och nu vägrar PostgreSQL att börja med PANIC: could not locate a valid checkpoint record. Går all data förlorad?

Nej, de flesta tabellraderna är fortfarande inne $PGDATA/bas/, även om transaktioner ombord i de raderade WAL-filerna går förlorade och vissa sidor kan slitas sönder. Gör först en fullständig kopia av hela $PGDATA katalog (cp -a /var/lib/postgresql/16/main /mnt/backup/pgdata_raw). Spring sedan sudo -u postgres /usr/lib/postgresql/16/bin/pg_resetwal -f /var/lib/postgresql/16/main, starta PostgreSQL i enanvändarläge och kör omedelbart pg_dumpall till en nyinitierad (initdb) kluster; fortsätt aldrig att köra produktionstrafik på ett kluster efteråt pg_resetwal.

Hur tar jag bort miljontals små filer när rm -rf hänger eller går sönder på en inod som är utmattad (df -i 100%) server?

När en katalog innehåller miljontals små sessions- eller cachefiler, kommer dess katalogindex (htree) växer enormt, orsakar ls och rm -rf för att stoppa sortering av filnamn i RAM. Spring istället sudo hitta /sökväg/till/million_filer -mindepth 1 -radera, eller skapa en tom RAM-katalog (mkdir /dev/shm/empty) och kör sudo rsync -a --radera /dev/shm/empty/ /path/to/million_files/ för att snabbt koppla bort inoder.

Varför fyllde Docker upp hela min serverdisk när mina containrar i sig är små, och hur rengör jag /var/lib/docker säkert?

Docker ackumulerar diskutrymme i oroterade JSON standardloggar (/var/lib/docker/containers/*/*-json.log), dinglande överlägg 2 bildlager och buildkit-cache. Aldrig manuellt rm -rf mappar inuti /var/lib/docker/overlay2/. Först trunkera JSON-loggarna (sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log) så demonen har andrum, kör sedan sudo docker system prune -a -f (utelämnar --volymer så databasvolymer förblir orörda).

Kan jag utöka en moln EBS / persistent diskvolym live medan servern har 100 % diskutnyttjande?

Ja, onlinevolymexpansion fungerar utan omstart, med en hake: hjälparskriptet growpart /dev/nvme0n1 1 försöker skapa en temporär fil i /tmp använder mktemp och misslyckas med 0 byte gratis. Förbi det misslyckandet genom att springa sudo TMPDIR=/dev/shm growpart /dev/nvme0n1 1 (med det RAM-stödda /dev/shm montera) följt av sudo resize2fs /dev/nvme0n1p1 (ext4) eller sudo xfs_growfs / (XFS).


Relaterade guider


Källor och officiell vägledning

  • PostgreSQL Global Development Group: Officiell dokumentation för PostgreSQL 16 - Kapitel 30: Tillförlitlighet och Write-Ahead-loggen (WAL-konfiguration, replikeringsplatser och återställning från diskfulla fel).
  • SQLite Consortium (sqlite.org): Hur man korrumperar en SQLite-databasfil (fillåsning, olänkade journal-/WAL-filer och .recover CLI-tillägg).
  • Oracle Corporation / MySQL Documentation & MariaDB Foundation: InnoDB Crash Recovery, Binary Log Purge Procedures (PURGE BINARY LOGS), och Temporary Tablespace (ibtmp1) Ledning.
  • Linux Kernel Organisation (kernel.org): Ext4 filsystemadministration (tune2fs Reserverade block, inodtabeller och /proc/<pid>/fd/ File Descriptor Trunkering).
  • National Institute of Standards and Technology (NIST) (USA): Specialpublikation 800-123: Guide to General Server Security and Availability Management.