MariaDB
 sql >> Base de Dados >  >> RDS >> MariaDB

Meu banco de dados MySQL está sem espaço em disco

Quando o servidor MySQL ficasse sem espaço em disco, você veria um dos seguintes erros em seu aplicativo (assim como no log de erros do MySQL):

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

Para log binário, a mensagem de erro se parece com isso:
[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.

Para o log de retransmissão, a mensagem de erro se parece com isso:
[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.

Para log de consulta lenta, você verá uma mensagem de erro como esta:
[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.

Para o InnoDB, fica assim:
[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 ./#

Todos eles estão relatando o mesmo número de código de erro que é 28. Alternativamente, podemos usar o código de erro para ver o erro real com o comando perror:
$ perror 28
OS error code  28: No space left on device

O acima simplesmente significa que o servidor MySQL está sem espaço em disco, e na maioria das vezes o MySQL está parado ou travado neste ponto. Nesta postagem do blog, veremos maneiras de resolver esse problema para o MySQL em execução em um ambiente baseado em Linux.

Solução de problemas

Primeiro de tudo, temos que determinar qual partição do disco está cheia. O MySQL pode ser configurado para armazenar dados em um disco ou partição diferente. Olhe para o caminho conforme indicado no erro para começar. Neste exemplo, nosso diretório está localizado no local padrão, /var/lib/mysql, que está sob a partição /. Podemos usar o comando df e especificar o caminho completo para o datadir para obter a partição em que os dados estão armazenados:

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

O acima significa que temos que liberar algum espaço na partição raiz.

Soluções temporárias

A solução temporária é liberar algum espaço em disco para que o MySQL possa gravar no disco e retomar a operação. As coisas que podemos fazer se enfrentarmos esse tipo de problema estão relacionadas a:

  • A remoção de arquivos desnecessários
  • Limpeza dos logs binários
  • Descartar tabelas antigas ou reconstruir uma tabela muito grande

Remover arquivos desnecessários

Este é geralmente o primeiro passo a ser feito se o servidor MySQL estiver inativo ou não responder, ou se você não tiver logs binários habilitados. Por exemplo, arquivos em /var/log/ geralmente são o primeiro lugar para procurar arquivos desnecessários:

$ 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

O exemplo acima mostra como recuperar arquivos maiores que 5 MB. Podemos remover com segurança os arquivos de log girados que geralmente estão no formato {filename}.{number}, por exemplo, de audit.log.1 até audit.log.6. A mesma coisa pode ser dita sobre qualquer backup antigo enorme armazenado no servidor. Se você realizou uma restauração via Percona Xtrabackup ou MariaDB Backup, todos os arquivos prefixados com xtrabackup_ podem ser removidos do diretório de dados do MySQL, pois não são mais necessários para a restauração. O xtrabackup_logfile geralmente é o maior arquivo, pois contém todas as transações executadas enquanto o processo xtrabackup copia o datadir para o destino. O exemplo a seguir mostra todos os arquivos relacionados no diretório de dados do MySQL:
$ 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

Portanto, os arquivos mencionados são seguros para serem excluídos. Inicie o serviço MySQL quando houver pelo menos 10% mais espaço livre.

Limpar os logs binários

Se o servidor MySQL ainda for responsivo e tiver log binário ativado, por exemplo, para replicação ou recuperação pontual, podemos limpar os arquivos de log binários antigos usando a instrução PURGE e fornecendo o intervalo. Neste exemplo, estamos excluindo todos os logs binários antes de 3 dias atrás:

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

Para a Replicação do MySQL, é seguro excluir todos os logs que foram replicados e aplicados nos escravos. Verifique o valor Relay_Master_Log_File no servidor:
mysql> SHOW SLAVE STATUS\G
...
        Relay_Master_Log_File: binlog.000008
...

E exclua os arquivos de log mais antigos, por exemplo, binlog.000007 e mais antigos. É uma boa prática reiniciar o servidor MySQL para garantir que ele tenha recursos suficientes. Também podemos permitir que a rotação do log binário aconteça automaticamente por meio da variável expire_logs_days (

mysql> SET GLOBAL expire_logs_days = 3;

Em seguida, adicione a seguinte linha no arquivo de configuração do MySQL na seção [mysqld]:
expire_logs_days=3

No MySQL 8.0, use binlog_expire_logs_seconds em vez disso, onde o valor padrão é 2592000 segundos (30 dias). Neste exemplo, reduzimos para apenas 3 dias (60 segundos x 60 minutos x 24 horas x 3 dias):
mysql> SET GLOBAL binlog_expire_logs_seconds = (60*60*24*3);
mysql> SET PERSIST binlog_expire_logs_seconds = (60*60*24*3);

SET PERSIST garantirá que a configuração seja carregada na próxima reinicialização. A configuração definida por este comando é armazenada em /var/lib/mysql/mysqld-auto.cnf.

Soltar tabelas antigas/reconstruir tabelas

Observe que a operação DELETE não liberará espaço em disco, a menos que OPTIMIZE TABLE seja executado posteriormente. Assim, se você excluiu muitas linhas e gostaria de retornar o espaço livre de volta ao sistema operacional após uma operação DELETE enorme, execute o OPTIMIZE TABLE ou reconstrua-o. Por exemplo:

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

Também podemos forçar a reconstrução de uma tabela usando a instrução ALTER:
mysql> ALTER TABLE tbl_name FORCE;
mysql> ALTER TABLE tbl_name; -- a.k.a "null" rebuild

Observe que a operação DDL acima é realizada via DDL online, o que significa que o MySQL permite operações DML simultâneas enquanto a reconstrução está em andamento. Outra maneira de realizar uma operação de desfragmentação é usar mysqldump para despejar a tabela em um arquivo de texto, descartar a tabela e recarregá-la a partir do arquivo de despejo. Por fim, também podemos usar DROP TABLE para remover a tabela não utilizada ou TRUNCATE TABLE para limpar todas as linhas da tabela, o que consequentemente retorna o espaço de volta ao sistema operacional.

Soluções permanentes para problemas de espaço em disco

A solução permanente é, obviamente, adicionar mais espaço ao disco ou partição correspondente ou aplicar uma regra de retenção mais curta para manter arquivos desnecessários no servidor. Se você estiver executando em um sistema de armazenamento de arquivos escalável, poderá aumentar o recurso sem muitos problemas ou com o mínimo de interrupção e tempo de inatividade para o serviço MySQL. Para saber mais sobre como dimensionar seu armazenamento e entender o planejamento de capacidade do MySQL e do MariaDB, confira esta postagem do blog.

Resumo


Problemas de banco de dados relacionados ao disco são um dos problemas mais prevalentes em relação aos administradores e desenvolvedores de banco de dados MySQL que trabalham com o RDBMS - no entanto, embora esses problemas possam ser predominantes, também existem muitas maneiras de resolvê-los - e resolvê-los para sempre. As maneiras de lidar com esse problema nem sempre são simples, no entanto, todas elas podem ser resolvidas com um pouco de esforço e assistência fornecida por ferramentas como o ClusterControl.

Com os recursos de monitoramento proativo do ClusterControl, os problemas relacionados ao banco de dados devem ser a menor de suas preocupações:você receberá uma notificação na forma de um aviso quando o espaço em disco atingir 80% e uma notificação na forma de um aviso crítico se o seu o uso do disco atinge 90% ou mais. Esperamos que esta postagem do blog tenha permitido que você resolva pelo menos alguns dos problemas relacionados ao uso do espaço em disco do MySQL, aproveite o uso do ClusterControl e nos veremos no próximo blog.