Quando il server MySQL esaurisce lo spazio su disco, viene visualizzato uno dei seguenti errori nell'applicazione (oltre che nel registro degli errori MySQL):
ERROR 3 (HY000) at line 1: Error writing file '/tmp/AY0Wn7vA' (Errcode: 28 - No space left on device)
Per il log binario il messaggio di errore appare così:
[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.
Per il registro di inoltro il messaggio di errore è simile al seguente:
[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.
Per il registro delle query lente vedresti un messaggio di errore come questo:
[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.
Per InnoDB sembra così:
[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 ./#
Stanno tutti segnalando lo stesso numero di codice di errore che è 28. In alternativa, possiamo usare il codice di errore per vedere l'errore effettivo con il comando perror:
$ perror 28
OS error code 28: No space left on device
Quanto sopra significa semplicemente che il server MySQL ha esaurito lo spazio su disco e la maggior parte delle volte MySQL viene arrestato o bloccato a questo punto. In questo post del blog, esamineremo i modi per risolvere questo problema per MySQL in esecuzione in un ambiente basato su Linux.
Risoluzione dei problemi
Prima di tutto, dobbiamo determinare quale partizione del disco è piena. MySQL può essere configurato per archiviare i dati su un disco o una partizione diversi. Guarda il percorso come indicato nell'errore per cominciare. In questo esempio, la nostra directory si trova nella posizione predefinita, /var/lib/mysql che si trova sotto la partizione /. Possiamo usare il comando df e specificare il percorso completo della datadir per ottenere la partizione in cui sono archiviati i dati:
$ df -h /var/lib/mysql
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 40G 40G 20K 100% /
Quanto sopra significa che dobbiamo liberare un po' di spazio nella partizione di root.
Soluzioni temporanee
La soluzione temporanea consiste nel liberare spazio su disco in modo che MySQL possa scrivere sul disco e riprendere l'operazione. Le cose che possiamo fare se affrontiamo questo tipo di problema sono legate a:
- La rimozione dei file non necessari
- Eliminazione dei log binari
- Eliminazione di vecchie tabelle o ricostruzione di una tabella molto grande
Rimuovi i file non necessari
Questo è comunemente il primo passo da fare se il server MySQL è inattivo o non risponde, o se non hai i log binari abilitati. Ad esempio, i file in /var/log/ sono comunemente il primo posto in cui cercare i file non necessari:
$ 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
L'esempio sopra mostra come recuperare file di dimensioni superiori a 5 MB. Possiamo rimuovere in modo sicuro i file di registro ruotati che di solito sono in formato {filename}.{number}, ad esempio da audit.log.1 fino a audit.log.6. La stessa cosa si può dire di tutti i vecchi backup enormi archiviati nel server. Se hai eseguito un ripristino tramite Percona Xtrabackup o MariaDB Backup, tutti i file con il prefisso xtrabackup_ possono essere rimossi dalla directory dati MySQL, poiché non sono più necessari per il ripristino. Il file xtrabackup_log di solito è il file più grande poiché contiene tutte le transazioni eseguite mentre il processo xtrabackup copia la datadir nella destinazione. L'esempio seguente mostra tutti i file correlati in 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
Pertanto, i file menzionati possono essere eliminati in modo sicuro. Avvia il servizio MySQL quando c'è almeno il 10% di spazio libero in più.
Elimina i log binari
Se il server MySQL è ancora reattivo e ha il log binario abilitato, ad esempio per la replica o il ripristino point-in-time, possiamo eliminare i vecchi file di log binari utilizzando l'istruzione PURGE e fornendo il intervallo. In questo esempio, stiamo eliminando tutti i log binari prima di 3 giorni fa:
mysql> SHOW BINARY LOGS;
mysql> PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 3 DAY);
mysql> SHOW BINARY LOGS;
Per MySQL Replication, è possibile eliminare tutti i log che sono stati replicati e applicati sugli slave. Controllare il valore Relay_Master_Log_File sul server:
mysql> SHOW SLAVE STATUS\G
...
Relay_Master_Log_File: binlog.000008
...
E elimina i file di registro meno recenti, ad esempio binlog.000007 e precedenti. È buona norma riavviare il server MySQL per assicurarsi che disponga di risorse sufficienti. Possiamo anche lasciare che la rotazione del log binario avvenga automaticamente tramite la variabile require_logs_days (
Quindi, aggiungi la seguente riga nel file di configurazione di MySQL nella sezione [mysqld]:
In MySQL 8.0, usa invece binlog_expire_logs_seconds, dove il valore predefinito è 2592000 secondi (30 giorni). In questo esempio, lo riduciamo a soli 3 giorni (60 secondi x 60 minuti x 24 ore x 3 giorni):
SET PERSIST assicurerà che la configurazione venga caricata al prossimo riavvio. La configurazione impostata da questo comando è memorizzata all'interno di /var/lib/mysql/mysqld-auto.cnf. Tieni presente che l'operazione DELETE non libererà spazio su disco a meno che non venga eseguito OPTIMIZE TABLE in seguito. Pertanto, se hai eliminato molte righe e desideri restituire lo spazio libero al sistema operativo dopo un'enorme operazione DELETE, esegui OPTIMIZE TABLE o ricostruiscilo. Ad esempio:
Possiamo anche forzare la ricostruzione di una tabella usando l'istruzione ALTER:
Si noti che l'operazione DDL di cui sopra viene eseguita tramite DDL online, il che significa che MySQL consente operazioni DML simultanee mentre la ricostruzione è in corso. Un altro modo per eseguire un'operazione di deframmentazione consiste nell'usare mysqldump per eseguire il dump della tabella in un file di testo, rilasciare la tabella e ricaricarla dal file di dump. Infine, possiamo anche utilizzare DROP TABLE per rimuovere la tabella inutilizzata o TRUNCATE TABLE per ripulire tutte le righe della tabella, che di conseguenza restituiscono lo spazio al sistema operativo. La soluzione permanente è ovviamente aggiungere più spazio al disco o alla partizione corrispondente o applicare una regola di conservazione più breve per mantenere i file non necessari nel server. Se stai utilizzando un sistema di archiviazione di file scalabile, dovresti essere in grado di aumentare la risorsa senza troppi problemi o con interruzioni e tempi di inattività minimi per il servizio MySQL. Per ulteriori informazioni su come dimensionare lo storage e comprendere la pianificazione della capacità di MySQL e MariaDB, dai un'occhiata a questo post del blog.
I problemi di database relativi al disco sono uno dei problemi più diffusi per quanto riguarda gli amministratori di database MySQL e gli sviluppatori che lavorano con l'RDBMS allo stesso modo, tuttavia, sebbene questi problemi possano essere prevalenti, ci sono anche molti modi per risolverli e risolverli per sempre. I modi per affrontare un problema del genere potrebbero non essere sempre semplici, tuttavia, tutti possono essere risolti con un po' di impegno e assistenza fornita da strumenti come ClusterControl.
Con le capacità di monitoraggio proattivo di ClusterControl, i problemi relativi al database dovrebbero essere l'ultima delle tue preoccupazioni:riceverai una notifica sotto forma di avviso quando lo spazio su disco ha raggiunto l'80% e una notifica sotto forma di avviso critico se il tuo l'utilizzo del disco raggiunge il 90% o più. Ci auguriamo che questo post sul blog ti abbia permesso di risolvere almeno un paio di problemi relativi all'utilizzo dello spazio su disco MySQL, divertirti con ClusterControl e ci vediamo nel prossimo blog.mysql> SET GLOBAL expire_logs_days = 3;
expire_logs_days=3
mysql> SET GLOBAL binlog_expire_logs_seconds = (60*60*24*3);
mysql> SET PERSIST binlog_expire_logs_seconds = (60*60*24*3);
Elimina le vecchie tabelle / Ricostruisci le tabelle
mysql> DELETE tbl_name WHERE id < 100000; -- remove 100K rows
mysql> OPTIMIZE TABLE tbl_name;
mysql> ALTER TABLE tbl_name FORCE;
mysql> ALTER TABLE tbl_name; -- a.k.a "null" rebuild
Soluzioni permanenti ai problemi di spazio su disco
Riepilogo