sql >> Databasteknik >  >> RDS >> MariaDB

Min MySQL-databas är slut på diskutrymme

När MySQL-servern fick slut på diskutrymme, skulle du se ett av följande fel i din applikation (liksom i MySQL-felloggen):

ERROR 3 (HY000) at line 1: Error writing file '/tmp/AY0Wn7vA' (Errcode: 28 - No space left on device)

För binär logg ser felmeddelandet ut så här:

[ERROR] [MY-000035] [Server] Disk is full writing './binlog.000019' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.

För relälogg ser felmeddelandet ut så här:

[ERROR] [MY-000035] [Server] Disk is full writing './relay-bin.000007' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.

För långsam frågelogg skulle du se ett felmeddelande som så här:

[ERROR] [MY-011263] [Server] Could not use /var/log/mysql/mysql-slow.log for logging (error 28 - No space left on device). Turning logging off for the server process. To turn it on again: fix the cause, then either restart the query logging by using "SET GLOBAL SLOW_QUERY_LOG=ON" or restart the MySQL server.

För InnoDB ser det ut så här:

[ERROR] [MY-012144] [InnoDB] posix_fallocate(): Failed to preallocate data for file ./#innodb_temp/temp_8.ibt, desired size 16384 bytes. Operating system error number 28. Check that the disk is not full or a disk quota exceeded. Make sure the file system supports this function. Some operating system error numbers are described at http://dev.mysql.com/doc/refman/8.0/en/operating-system-error-codes.html
[Warning] [MY-012638] [InnoDB] Retry attempts for writing partial data failed.
[ERROR] [MY-012639] [InnoDB] Write to file ./#innodb_temp/temp_8.ibt failed at offset 81920, 16384 bytes should have been written, only 0 were written. Operating system error number 28. Check that your OS and file system support files of this size. Check also that the disk is not full or a disk quota exceeded.
[ERROR] [MY-012640] [InnoDB] Error number 28 means 'No space left on device'
[Warning] [MY-012145] [InnoDB] Error while writing 16384 zeroes to ./#

De rapporterar alla samma felkod som är 28. Alternativt kan vi använda felkoden för att se det faktiska felet med kommandot perror:

$ perror 28
OS error code  28: No space left on device

Ovanstående betyder helt enkelt att MySQL-servern har slut på diskutrymme, och för det mesta är MySQL stoppad eller avstannad vid denna tidpunkt. I det här blogginlägget kommer vi att undersöka sätt att lösa det här problemet för MySQL som körs i en Linux-baserad miljö.

Felsökning

Först och främst måste vi bestämma vilken diskpartition som är full. MySQL kan konfigureras för att lagra data på en annan disk eller partition. Titta på sökvägen som anges i felet till att börja med. I det här exemplet finns vår katalog på standardplatsen, /var/lib/mysql som finns under /-partitionen. Vi kan använda kommandot df och ange den fullständiga sökvägen till datakatalogen för att få partitionen som data lagras:

$ df -h /var/lib/mysql
Filesystem      Size Used Avail Use% Mounted on
/dev/sda1        40G 40G 20K 100% /

Ovanstående betyder att vi måste rensa upp lite utrymme i rotpartitionen.

Tillfälliga lösningar

Den tillfälliga lösningen är att frigöra lite diskutrymme så att MySQL kan skriva till disken och återuppta operationen. Saker som vi kan göra om vi möter den här typen av problem är relaterade till:

  • Ta bort onödiga filer
  • Resning av de binära loggarna
  • Att släppa gamla tabeller eller bygga om ett väldigt stort bord

Ta bort onödiga filer

Detta är vanligtvis det första steget att göra om MySQL-servern är nere eller inte svarar, eller om du inte har några binära loggar aktiverade. Till exempel är filer under /var/log/ vanligtvis det första stället att leta efter onödiga filer:

$ cd /var/log
$ find . -type f -size +5M -exec du -sh {} +
8.1M ./audit/audit.log.6
8.1M ./audit/audit.log.5
8.1M ./audit/audit.log.4
8.1M ./audit/audit.log.3
8.1M ./audit/audit.log.2
8.1M ./audit/audit.log.1
11M ./audit/audit.log
8.5M ./secure-20190429
8.0M ./wtmp

Exemplet ovan visar hur man hämtar filer som är större än 5MB. Vi kan säkert ta bort de roterade loggfilerna som vanligtvis är i formatet {filename}.{number}, till exempel från audit.log.1 till audit.log.6. Samma sak kan sägas om alla stora äldre säkerhetskopior som finns lagrade på servern. Om du hade utfört en återställning via Percona Xtrabackup eller MariaDB Backup, kan alla filer med prefixet xtrabackup_ tas bort från MySQL datadir, eftersom de inte längre är nödvändiga för återställningen. Xtrabackup_logfilen är vanligtvis den största filen eftersom den innehåller alla transaktioner som utförs medan xtrabackup-processen kopierar datafilen till destinationen. Följande exempel visar alla relaterade filer i MySQL datadir:

$ ls -lah /var/lib/mysql | grep xtrabackup_
-rw-r-----.  1 mysql root   286 Feb 4 11:30 xtrabackup_binlog_info
-rw-r--r--.  1 mysql root    24 Feb 4 11:31 xtrabackup_binlog_pos_innodb
-rw-r-----.  1 mysql root    83 Feb 4 11:31 xtrabackup_checkpoints
-rw-r-----.  1 mysql root   808 Feb 4 11:30 xtrabackup_info
-rw-r-----.  1 mysql root  179M Feb 4 11:31 xtrabackup_logfile
-rw-r--r--.  1 mysql root     1 Feb 4 11:31 xtrabackup_master_key_id
-rw-r-----.  1 mysql root   248 Feb 4 11:31 xtrabackup_tablespaces

Därför är de nämnda filerna säkra att raderas. Starta MySQL-tjänsten när det finns minst 10 % mer ledigt utrymme.

Rensa de binära loggarna

Om MySQL-servern fortfarande är responsiv och den har aktiverad binär logg, t.ex. för replikering eller punktåterställning, kan vi rensa de gamla binära loggfilerna genom att använda PURGE-satsen och tillhandahålla intervall. I det här exemplet tar vi bort alla binära loggar för tre dagar sedan:

mysql> SHOW BINARY LOGS;
mysql> PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 3 DAY);
mysql> SHOW BINARY LOGS;

För MySQL-replikering är det säkert att ta bort alla loggar som har replikerats och applicerats på slavar. Kontrollera värdet Relay_Master_Log_File på servern:

mysql> SHOW SLAVE STATUS\G
...
        Relay_Master_Log_File: binlog.000008
...

Och ta bort de äldre loggfilerna till exempel binlog.000007 och äldre. Det är bra att starta om MySQL-servern för att se till att den har tillräckligt med resurser. Vi kan också låta den binära loggrotationen ske automatiskt via variabeln expire_logs_days (

mysql> SET GLOBAL expire_logs_days = 3;

Lägg sedan till följande rad i MySQL-konfigurationsfilen under avsnittet [mysqld]:

expire_logs_days=3

I MySQL 8.0, använd istället binlog_expire_logs_seconds, där standardvärdet är 2592000 sekunder (30 dagar). I det här exemplet minskar vi det till endast 3 dagar (60 sekunder x 60 minuter x 24 timmar x 3 dagar):

mysql> SET GLOBAL binlog_expire_logs_seconds = (60*60*24*3);
mysql> SET PERSIST binlog_expire_logs_seconds = (60*60*24*3);

SET PERSIST ser till att konfigurationen laddas vid nästa omstart. Konfiguration som ställs in av detta kommando lagras i /var/lib/mysql/mysqld-auto.cnf.

Släpp gamla tabeller / Bygg om tabeller

Observera att DELETE operationen inte frigör diskutrymme om inte OPTIMIZE TABLE körs efteråt. Således, om du har raderat många rader och du vill återställa det lediga utrymmet till OS efter en enorm DELETE-operation, kör OPTIMERA TABELL, eller bygg om den. Till exempel:

mysql> DELETE tbl_name WHERE id < 100000; -- remove 100K rows
mysql> OPTIMIZE TABLE tbl_name;

Vi kan också tvinga att bygga om en tabell genom att använda ALTER-satsen:

mysql> ALTER TABLE tbl_name FORCE;
mysql> ALTER TABLE tbl_name; -- a.k.a "null" rebuild

Observera att ovanstående DDL-operation utförs via online-DDL, vilket innebär att MySQL tillåter samtidiga DML-operationer medan ombyggnaden pågår. Ett annat sätt att utföra en defragmenteringsoperation är att använda mysqldump för att dumpa tabellen till en textfil, släppa tabellen och ladda om den från dumpfilen. I slutändan kan vi också använda DROP TABLE för att ta bort den oanvända tabellen eller TRUNCATE TABLE för att rensa alla rader i tabellen, vilket följaktligen returnerar utrymmet tillbaka till operativsystemet.

Permanenta lösningar på diskutrymmesproblem

Den permanenta lösningen är naturligtvis att lägga till mer utrymme till motsvarande disk eller partition, eller att tillämpa en kortare lagringsregel för att behålla onödiga filer på servern. Om du kör ovanpå ett skalbart fillagringssystem bör du kunna skala upp resursen utan alltför mycket krångel, eller med minimala avbrott och driftstopp för MySQL-tjänsten. För att lära dig mer om hur du dimensionerar din lagring och förstår MySQL- och MariaDB-kapacitetsplanering, kolla in det här blogginlägget.

Sammanfattning

Diskrelaterade databasproblem är ett av de vanligaste problemen som gäller MySQL-databasadministratörer och utvecklare som arbetar med RDBMS - men även om dessa problem kan vara vanliga finns det också många sätt att lösa dem - och lösa dem för gott. Sätten att ta itu med ett sådant problem kanske inte alltid är enkla, men de kan alla lösas med lite ansträngning och hjälp från verktyg som ClusterControl.

Med ClusterControls proaktiva övervakningsmöjligheter bör databasrelaterade problem vara det minsta du oroar dig för:du får ett meddelande i form av en varning när diskutrymmet har nått 80 %, och ett meddelande i form av en kritisk varning om din diskanvändningen når 90 % eller mer. Vi hoppas att det här blogginlägget har låtit dig lösa åtminstone ett par av problemen relaterade till användning av MySQL-diskutrymme, njut av din användning av ClusterControl, och vi ses i nästa blogg.


  1. JSON_MERGE_PATCH() vs JSON_MERGE_PRESERVE() i MySQL:Vad är skillnaden?

  2. Hur LOWER()-funktionen fungerar i MySQL

  3. Dela en partition i två i SQL Server (T-SQL)

  4. Hur anropar man en MySQL-lagrad procedur från PHP-kod?