Když na serveru MySQL dojde místo na disku, uvidíte ve své aplikaci (a také v protokolu chyb MySQL) jednu z následujících chyb:
ERROR 3 (HY000) at line 1: Error writing file '/tmp/AY0Wn7vA' (Errcode: 28 - No space left on device)
Pro binární protokol vypadá chybová zpráva takto:
[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.
Pro protokol přenosu vypadá chybová zpráva takto:
[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.
U pomalého protokolu dotazů by se zobrazila chybová zpráva, jako je tato:
[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.
Pro InnoDB to vypadá takto:
[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 ./#
Všechny hlásí stejný kód chyby, který je 28. Případně můžeme kód chyby použít k zobrazení skutečné chyby pomocí příkazu perror:
$ perror 28
OS error code 28: No space left on device
Výše uvedené jednoduše znamená, že server MySQL nemá místo na disku a většinu času je MySQL v tomto bodě zastaveno nebo zastaveno. V tomto příspěvku na blogu se podíváme na způsoby, jak vyřešit tento problém pro MySQL běžící v prostředí založeném na Linuxu.
Odstraňování problémů
Nejprve musíme určit, který diskový oddíl je plný. MySQL lze nakonfigurovat tak, aby ukládala data na jiný disk nebo oddíl. Pro začátek se podívejte na cestu uvedenou v chybě. V tomto příkladu je náš adresář umístěn ve výchozím umístění /var/lib/mysql, které je v oddílu /. Můžeme použít příkaz df a zadat úplnou cestu k datovému adresáři, abychom získali oddíl, kde jsou data uložena:
$ df -h /var/lib/mysql
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 40G 40G 20K 100% /
Výše uvedené znamená, že musíme uvolnit nějaké místo v kořenovém oddílu.
Dočasná zástupná řešení
Dočasným řešením je uvolnit místo na disku, aby mohla MySQL zapisovat na disk a pokračovat v operaci. Věci, které můžeme dělat, pokud čelíme tomuto druhu problému, souvisí s:
- Odebrání nepotřebných souborů
- Čištění binárních protokolů
- Odstranění starých stolů nebo přestavba velmi velkého stolu
Odstraňte nepotřebné soubory
Toto je obvykle první krok, který musíte udělat, pokud je MySQL server mimo provoz, nereaguje nebo nemáte povoleny žádné binární protokoly. Například soubory pod /var/log/ jsou obvykle prvním místem, kde hledat nepotřebné soubory:
$ 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
Výše uvedený příklad ukazuje, jak načíst soubory, které jsou větší než 5 MB. Můžeme bezpečně odstranit rotované soubory protokolu, které jsou obvykle ve formátu {filename}.{number}, například z audit.log.1 do audit.log.6. Totéž lze říci o všech velkých starších zálohách, které jsou uloženy na serveru. Pokud jste provedli obnovu pomocí Percona Xtrabackup nebo MariaDB Backup, všechny soubory s předponou xtrabackup_ lze odstranit z datadir MySQL, protože již nejsou pro obnovu nutné. Soubor xtrabackup_logfile je obvykle největší soubor, protože obsahuje všechny transakce provedené během procesu xtrabackup kopírování datového adresáře do cíle. Následující příklad ukazuje všechny související soubory v 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
Uvedené soubory lze tedy bezpečně smazat. Spusťte službu MySQL, jakmile bude alespoň o 10 % více volného místa.
Vyčistit binární protokoly
Pokud server MySQL stále reaguje a má povolený binární protokol, např. pro replikaci nebo obnovu v určitém okamžiku, můžeme vymazat staré binární soubory protokolu pomocí příkazu PURGE a poskytnutí interval. V tomto příkladu odstraňujeme všechny binární protokoly před 3 dny:
mysql> SHOW BINARY LOGS;
mysql> PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 3 DAY);
mysql> SHOW BINARY LOGS;
Pro replikaci MySQL je bezpečné odstranit všechny protokoly, které byly replikovány a aplikovány na podřízené jednotky. Zkontrolujte hodnotu Relay_Master_Log_File na serveru:
mysql> SHOW SLAVE STATUS\G
...
Relay_Master_Log_File: binlog.000008
...
A odstraňte starší soubory protokolu, například binlog.000007 a starší. Je dobrým zvykem restartovat server MySQL, abyste se ujistili, že má dostatek prostředků. Můžeme také nechat, aby rotace binárního protokolu probíhala automaticky prostřednictvím proměnné expire_logs_days (
Poté přidejte následující řádek do konfiguračního souboru MySQL v sekci [mysqld]:
V MySQL 8.0 použijte místo toho binlog_expire_logs_seconds, kde výchozí hodnota je 2592000 sekund (30 dní). V tomto příkladu to zkrátíme pouze na 3 dny (60 sekund x 60 minut x 24 hodin x 3 dny):
SET PERSIST zajistí načtení konfigurace při příštím restartu. Konfigurace nastavená tímto příkazem je uložena v /var/lib/mysql/mysqld-auto.cnf. Upozorňujeme, že operace DELETE neuvolní místo na disku, pokud následně nespustíte OPTIMIZE TABLE. Pokud jste tedy odstranili mnoho řádků a chtěli byste po rozsáhlé operaci DELETE vrátit volné místo zpět do operačního systému, spusťte OPTIMALIZAČNÍ TABULKU nebo ji znovu sestavte. Například:
Můžeme také vynutit opětovné sestavení tabulky pomocí příkazu ALTER:
Všimněte si, že výše uvedená operace DDL se provádí prostřednictvím online DDL, což znamená, že MySQL umožňuje souběžné operace DML, zatímco probíhá přestavba. Dalším způsobem, jak provést operaci defragmentace, je použít mysqldump k výpisu tabulky do textového souboru, zrušení tabulky a opětovnému načtení ze souboru výpisu. Nakonec můžeme také použít DROP TABLE k odstranění nepoužívané tabulky nebo TRUNCATE TABLE k vyčištění všech řádků v tabulce, což následně vrátí místo zpět do OS. Trvalým řešením je samozřejmě přidání více místa na odpovídající disk nebo oddíl nebo použití kratšího pravidla pro uchování nepotřebných souborů na serveru. Pokud používáte škálovatelný systém ukládání souborů, měli byste být schopni škálovat zdroj bez přílišných potíží nebo s minimálním přerušením a prostojem služby MySQL. Chcete-li se dozvědět více o tom, jak dimenzovat úložiště a porozumět plánování kapacity MySQL a MariaDB, podívejte se na tento blogový příspěvek.
Problémy s databází související s diskem jsou jedním z nejčastějších problémů správců databází MySQL a vývojářů pracujících s RDBMS – i když tyto problémy mohou převládat, existuje také mnoho způsobů, jak je vyřešit – a vyřešit je navždy. Způsoby, jak se s takovým problémem vypořádat, nemusí být vždy přímočaré, nicméně všechny lze vyřešit s trochou úsilí a pomoci poskytované nástroji jako ClusterControl.
S proaktivními monitorovacími možnostmi ClusterControl by měly být problémy související s databázemi tou nejmenší starostí:obdržíte upozornění ve formě varování, když místo na disku dosáhne 80 %, a upozornění ve formě kritického varování, pokud využití disku dosahuje 90 % nebo více. Doufáme, že vám tento příspěvek na blogu umožnil vyřešit alespoň několik problémů souvisejících s využitím místa na disku MySQL, užijete si používání ClusterControl a uvidíme se u dalšího blogu.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);
Vypustit staré tabulky / znovu vytvořit tabulky
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
Trvalá řešení problémů s místem na disku
Shrnutí