MySQLサーバーのディスク容量が不足すると、アプリケーション(およびMySQLエラーログ)に次のいずれかのエラーが表示されます。
ERROR 3 (HY000) at line 1: Error writing file '/tmp/AY0Wn7vA' (Errcode: 28 - No space left on device)
バイナリログの場合、エラーメッセージは次のようになります。
[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.
リレーログの場合、エラーメッセージは次のようになります。
[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.
クエリログが遅い場合は、次のようなエラーメッセージが表示されます。
[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.
InnoDBの場合は次のようになります:
[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 ./#
それらはすべて同じエラーコード番号28を報告しています。あるいは、エラーコードを使用して、perrorコマンドで実際のエラーを確認することもできます。
$ perror 28
OS error code 28: No space left on device
上記は単にMySQLサーバーのディスク容量が不足していることを意味し、ほとんどの場合、この時点でMySQLが停止または停止しています。このブログ投稿では、Linuxベースの環境で実行されているMySQLでこの問題を解決する方法を検討します。
まず、どのディスクパーティションがいっぱいかを判断する必要があります。 MySQLは、別のディスクまたはパーティションにデータを保存するように構成できます。最初にエラーに記載されているパスを確認してください。この例では、ディレクトリはデフォルトの場所である/ var / lib/mysqlにあります。これは/パーティションの下にあります。 dfコマンドを使用し、datadirへのフルパスを指定して、データが保存されているパーティションを取得できます。
$ df -h /var/lib/mysql
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 40G 40G 20K 100% /
上記は、ルートパーティションのスペースを空ける必要があることを意味します。
一時的な回避策は、MySQLがディスクに書き込んで操作を再開できるように、ディスクスペースを空けることです。この種の問題に直面した場合にできることは、次のことに関連しています。
- 古いテーブルを削除するか、非常に大きなテーブルを再構築します
これは通常、MySQLサーバーがダウンしているか応答しない場合、またはバイナリログが有効になっていない場合に実行する最初のステップです。たとえば、/ var / log /の下のファイルは、通常、不要なファイルを探す最初の場所です。
$ 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
上記の例は、5MBを超えるファイルを取得する方法を示しています。通常は{filename}。{number}形式のローテーションされたログファイルを安全に削除できます。たとえば、audit.log.1からaudit.log.6までです。サーバーに保存されている巨大な古いバックアップについても同じことが言えます。 PerconaXtrabackupまたはMariaDBBackupを介して復元を実行した場合、復元に不要になったため、xtrabackup_で始まるすべてのファイルをMySQLデータディレクトリから削除できます。 xtrabackup_logfileは、xtrabackupプロセスがdatadirを宛先にコピーしている間に実行されたすべてのトランザクションを含むため、通常は最大のファイルです。次の例は、MySQLdatadir内のすべての関連ファイルを示しています。
$ 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
したがって、上記のファイルは安全に削除できます。空き領域が少なくとも10%増えたら、MySQLサービスを開始します。
MySQLサーバーが引き続き応答し、バイナリログが有効になっている場合(レプリケーションやポイントインタイムリカバリなど)、PURGEステートメントを使用して古いバイナリログファイルを削除できます。間隔。この例では、3日前までにすべてのバイナリログを削除しています:
mysql> SHOW BINARY LOGS;
mysql> PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 3 DAY);
mysql> SHOW BINARY LOGS;
MySQLレプリケーションの場合、スレーブにレプリケートおよび適用されたすべてのログを安全に削除できます。サーバー上のRelay_Master_Log_File値を確認してください:
mysql> SHOW SLAVE STATUS\G
...
Relay_Master_Log_File: binlog.000008
...
そして、binlog.000007などの古いログファイルを削除します。 MySQLサーバーを再起動して、十分なリソースがあることを確認することをお勧めします。また、expire_logs_days変数(
次に、[mysqld]セクションの下のMySQL構成ファイルに次の行を追加します。
MySQL 8.0では、代わりにbinlog_expire_logs_secondsを使用します。デフォルト値は2592000秒(30日)です。この例では、3日(60秒x60分x24時間x3日)に短縮します。
SET PERSISTは、次回の再起動時に構成がロードされていることを確認します。このコマンドで設定された構成は、/ var / lib / mysql/mysqld-auto.cnf内に保存されます。 後でOPTIMIZETABLEを実行しない限り、DELETE操作ではディスク領域が解放されないことに注意してください。したがって、多くの行を削除し、大規模なDELETE操作の後に空き領域をOSに戻したい場合は、OPTIMIZE TABLEを実行するか、再構築します。例:
また、ALTERステートメントを使用してテーブルを強制的に再構築することもできます:
上記のDDL操作はオンラインDDLを介して実行されることに注意してください。つまり、MySQLは、再構築の進行中に同時DML操作を許可します。デフラグ操作を実行する別の方法は、mysqldumpを使用してテーブルをテキストファイルにダンプし、テーブルをドロップして、ダンプファイルからリロードすることです。最終的には、DROP TABLEを使用して未使用のテーブルを削除したり、TRUNCATE TABLEを使用してテーブル内のすべての行をクリアしたりすることもできます。これにより、スペースがOSに戻されます。 恒久的な解決策は、もちろん、対応するディスクまたはパーティションにスペースを追加するか、サーバーに不要なファイルを保持するために保持ルールを短くすることです。スケーラブルなファイルストレージシステム上で実行している場合は、あまり面倒なことなく、またはMySQLサービスの中断とダウンタイムを最小限に抑えて、リソースをスケールアップできるはずです。ストレージのサイズを決定し、MySQLとMariaDBの容量計画を理解する方法の詳細については、このブログ投稿を確認してください。
ディスク関連のデータベースの問題は、MySQLデータベース管理者とRDBMSを使用する開発者に関して最も一般的な問題の1つですが、これらの問題は一般的である可能性がありますが、それらを解決する方法もたくさんあります。このような問題に取り組む方法は必ずしも簡単ではないかもしれませんが、ClusterControlなどのツールによって提供される少しの努力と支援ですべてを解決することができます。
ClusterControlのプロアクティブな監視機能を使用すると、データベース関連の問題を最小限に抑えることができます。ディスク容量が80%に達したときに警告の形式で通知を受け取り、次の場合に重大な警告の形式で通知を受け取ります。ディスク使用量が90%以上に達します。このブログ投稿で、MySQLディスクスペースの使用に関連する問題の少なくともいくつかを解決し、ClusterControlの使用を楽しんでいただければ幸いです。また、次のブログでお会いしましょう。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);
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