Incidentu reaģēšana

Kā droši izdzēst MySQL bināros žurnālus, kad tie piepilda disku

Binārie žurnāli ir biežākais iemesls, kāpēc MySQL datu direktorija nemanot divkāršojas. Izdzēst tos ir vienkārši. Izdzēst tos, nesabojājot repliku vai atjaunošanu uz laika punktu, prasa piecas minūtes pārbaudes.

· 15 min lasīšanai · AG Data komanda

Nostrādā diska brīdinājums, jūs palaižat du MySQL datu direktorijā, un lielāko daļu vietas aizņem faili ar nosaukumu binlog.000xxx. Gribas ar rm izdzēst pusi no tiem. Nedariet tā. Pareizi izdzēst MySQL bināros žurnālus var ar vienu SQL komandu, bet tikai tad, kad zināt, kuri faili vēl vajadzīgi replikām, rezerves kopijām un atjaunošanas plānam. Šajā rakstā ir šī pārbaude, pati dzēšana un iestatījumi, kas neļauj situācijai atkārtoties.

Kāpēc binārie žurnāli krājas

MySQL 8.4 binārā žurnalēšana ir ieslēgta pēc noklusējuma un izmanto rindu formātu. Ja --log-bin nav norādīts tieši, faili saucas binlog.NNNNNN un atrodas datu direktorijā līdzās indeksa failam binlog.index, kurā tie uzskaitīti pēc kārtas. Saskaņā ar binārā žurnāla dokumentāciju serveris sāk jaunu failu, kad tas startē vai tiek restartēts, kad žurnāli tiek izskaloti (flush) un kad pašreizējais fails sasniedz max_binlog_size (noklusējums un maksimums ir 1GB). Viena transakcija nekad netiek sadalīta, tāpēc liels pakešu darbs var izveidot failu, kas krietni pārsniedz 1GB.

Vecie faili tiek dzēsti automātiski, kad tie kļūst vecāki par binlog_expire_logs_seconds. Noklusējums ir 2592000 sekundes jeb 30 dienas. Parasti tieši tas ir galvenais cēlonis: 30 dienu rindu līmeņa izmaiņas no aktīvi rakstošas lietotnes vienkārši ir vairāk, nekā diskam bija paredzēts. Tipiski izraisītāji:

1. solis: izmēriet, pirms dzēšat

df -h /var/lib/mysql
du -ch /var/lib/mysql/binlog.[0-9]* | tail -1
ls -lh /var/lib/mysql/binlog.index

Pēc tam paskatieties uz servera skatījumu:

SHOW BINARY LOGS;        -- Log_name, File_size, Encrypted
SHOW BINARY LOG STATUS;  -- fails, kurā serveris raksta pašlaik

SELECT @@log_bin, @@log_bin_basename,
       @@binlog_expire_logs_seconds, @@binlog_expire_logs_auto_purge,
       @@max_binlog_size, @@binlog_transaction_compression;

SHOW BINARY LOGS prasa REPLICATION CLIENT privilēģiju un parāda katru failu ar tā izmēru. Ja du un SHOW BINARY LOGS skaitļi stipri atšķiras, pirms turpināt, noskaidrojiet kāpēc: faili var būt iekopēti, izdzēsti ar roku vai palikuši ārpus indeksa.

Uztveriet to kā steidzamu. Rokasgrāmatas vispārējā sadaļā par pilnu disku teikts, ka MySQL reizi minūtē pārbauda, vai ir vieta turpināt, un ik pēc 10 minūtēm ieraksta brīdinājumu. Tomēr binārajam žurnālam ir savs noteikums: binlog_error_action noklusējums ir ABORT_SERVER, un tas liek serverim pārtraukt žurnalēšanu un izslēgties, ja tas nevar ierakstīt, izskalot vai sinhronizēt bināro žurnālu. Nepaļaujieties, ka rakstīšana vienkārši pagaidīs, kamēr atbrīvosiet vietu.

2. solis: noskaidrojiet, kas vēl vajadzīgs

Binārā žurnāla fails vēl tiek lietots, ja kāds to nav izlasījis līdz galam. Katrā replikā izpildiet:

-- KATRĀ replikā (un visur citur, kas lasa binlog)
SHOW REPLICA STATUS\G
--   Source_Log_File:        binlog.004211   (saņēmēja pavediens lasa šo)
--   Relay_Source_Log_File:  binlog.004209   (izpildītājs ir izpildījis līdz šejienei)

Dokumentācijā Source_Log_File definēts kā avota fails, ko saņēmēja (I/O) pavediens lasa pašlaik. Dzēšanai svarīgs ir tieši šis lauks, jo visu, kas ir pirms tā, replika jau ir saņēmusi. Vecākais Source_Log_File starp visām replikām ir jūsu mērķis: drīkst dzēst visu, kas ir pirms tā, bet neko no tā un tālāk.

Vēl divus lasītājus ir viegli aizmirst:

Ja kāda replika ļoti atpaliek, mūsu raksts par MySQL replikācijas aizturi skaidro, kāpēc tā notiek. To ir vērts novērst vispirms, jo tieši šī aizture uztur vecos binlog failus.

3. solis: dzēsiet ar SQL, nevis rm

-- saglabāt binlog.004211 un visus nākamos
PURGE BINARY LOGS TO 'binlog.004211';

-- vai pēc laika
PURGE BINARY LOGS BEFORE '2026-11-03 00:00:00';
PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY;

PURGE BINARY LOGS komanda izdzēš indeksā uzskaitītos failus, kas ir pirms norādītā nosaukuma vai datuma, un atjaunina binlog.index tā, lai norādītais fails kļūtu par pirmo. Tai vajadzīga BINLOG_ADMIN privilēģija. Oficiālā procedūra ir īsa: pārbaudiet SHOW REPLICA STATUS katrā replikā, iegūstiet SHOW BINARY LOGS avotā, izvēlieties agrāko failu, ko lasa kāda replika, izveidojiet dzēšamo failu rezerves kopiju (nav obligāti, bet ieteicams) un tad dzēsiet līdz šim failam, to neieskaitot.

Komandu ir droši izpildīt, kamēr replikas replicē; tās nav jāaptur. Ja pievienota replika lasa kādu no failiem, ko lūdzāt izdzēst, MySQL saglabā šo failu un visus nākamos, izdzēš tikai vecākos un izdod brīdinājumu. Šī aizsardzība attiecas tikai uz pievienotām replikām. Bezsaistē esošai replikai tā nepalīdz.

Divi ierobežojumi: PURGE BINARY LOGS nevar izpildīt, kamēr darbojas LOCK INSTANCE FOR BACKUP, un tai nav nekādas ietekmes, ja binārā žurnalēšana ir izslēgta.

Kāpēc rm situāciju pasliktina

Dzēšot failus ar roku, binlog.index joprojām norāda uz failiem, kuru vairs nav. Rokasgrāmata rezultātu apraksta skaidri: gan PURGE BINARY LOGS TO, gan PURGE BINARY LOGS BEFORE pēc tam beidzas ar kļūdu. Dokumentētais risinājums ir rediģēt indeksa failu (tas ir parasts teksts), atstāt tajā tikai tiešām esošos failus un izpildīt dzēšanu vēlreiz. Tātad rm sabojā tieši to rīku, kas būs vajadzīgs nākamreiz, un nekādi nepasargā replikas, kas vēl lasa.

Ja tas jau ir izdarīts, salabojiet indeksu pirms nākamās rotācijas vai restartēšanas un pārbaudiet katru repliku. Replika, kurai vajadzīgs izdzēsts fails, nevar turpināt. Servera kļūdu sarakstā ir ziņojumi, ko meklēt laukā Last_IO_Error: kļūda 1236, "Got fatal error ... from source when reading data from binary log", un GTID konfigurācijās ER_SOURCE_HAS_PURGED_REQUIRED_GTIDS, "Cannot replicate because the source purged required binary logs." Pašā ziņojumā ir uzskaitītas iespējas: iegūt trūkstošās transakcijas no citurienes vai izveidot repliku no jauna no rezerves kopijas. Mūsu raksts par replikācijas kļūdu 1062 skaidro, kāpēc notikumu izlaišana, lai repliku atkal palaistu, ir slikta doma; tas pats attiecas arī uz šo gadījumu.

Saglabājiet kopiju pirms dzēšanas

Ja neesat drošs, vai faili vēl būs vajadzīgi, pārvietojiet tos prom no servera, nevis pazaudējiet. mysqlbinlog rezerves kopēšanas režīms kopē bināros žurnālus to sākotnējā formātā caur parastu klienta savienojumu:

mysqlbinlog --read-from-remote-server --raw \
  --host=db1 --user=backup --password \
  --result-file=/backup/binlog/ \
  binlog.004100 binlog.004101 binlog.004102

--read-from-remote-server un --raw ir divas obligātās opcijas. Ievērojiet dokumentēto niansi: šādi izveidotas šifrētu bināro žurnālu kopijas tiek glabātas nešifrētas, tāpēc attiecīgi aizsargājiet rezerves kopiju vietu.

4. solis: novērsiet atkārtošanos

Iestatiet glabāšanas termiņu apzināti, nevis dzīvojiet ar 30 dienu noklusējumu:

[mysqld]
# 7 dienas; jābūt garākam par lielāko replikas aizturi
# un jāaptver periods starp pilnajām rezerves kopijām
binlog_expire_logs_seconds = 604800
binlog_transaction_compression = ON
SET PERSIST binlog_expire_logs_seconds = 604800;
FLUSH BINARY LOGS;   -- rotācija dod serverim iespēju izdzēst vecos failus

Pārvaldīts MySQL: Amazon RDS

RDS for MySQL bināro žurnālu glabāšanu iestata ar saglabāto procedūru. AWS dokumentācijā teikts, ka binlog retention hours noklusējums ir NULL, kas nozīmē, ka binārie žurnāli netiek glabāti, un maksimums ir 168 stundas (7 dienas):

CALL mysql.rds_set_configuration('binlog retention hours', 24);

Ja RDS instances krātuve turpina augt, pārbaudiet, vai kāds nav iestatījis ilgu glabāšanu ārējai replikai vai CDC rīkam, kura vairs nav.

Galvenās atziņas

MySQL Binārais žurnāls Replikācija Diska vieta
Sadarbība ar mums

MySQL serverī beidzas diska vieta?

Mēs droši atbrīvojam vietu, saglabājam replikas un atjaunošanas iespējas un iestatām glabāšanu tā, lai tas pats brīdinājums nākammēnes neatgrieztos.

Sazināties Vairāk no emuāra