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:
- Jauns pakešu darbs, datu imports vai pārrēķins, kas pārraksta miljoniem rindu. Rindu formātā žurnālā nonāk katra mainītā rinda.
- Disks izvēlēts datiem, nevis datiem kopā ar mēneša izmaiņām.
- Replikas:
log_replica_updatesir ieslēgts pēc noklusējuma, tāpēc katra replika ar ieslēgtu bināro žurnalēšanu glabā savu izmaiņu kopiju un var piepildīt arī savu disku. - Izslēgta automātiskā dzēšana.
binlog_expire_logs_auto_purge=OFFvaibinlog_expire_logs_seconds=0to pilnībā atslēdz.
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.
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:
- Replikas, kas pašlaik ir bezsaistē. Apturēta replika, atskaišu serveris, kas naktī ir izslēgts, vai replika, kas pagājušnedēļ atjaunota no momentuzņēmuma, neparādās kā aktīvs savienojums. Ja izdzēsīsiet failu, ko tā vēl nav izlasījusi, pēc atgriešanās tā nevarēs turpināt replicēt.
- Atjaunošana uz laika punktu un izmaiņu uztveršana. Ja atjaunojat no nakts pilnās rezerves kopijas un pēc tam atskaņojat bināros žurnālus, jums vajadzīgs katrs fails kopš vecākās rezerves kopijas, no kuras vēl plānojat atjaunot. Arī CDC rīki, piemēram, Debezium, lasa binlog, un tiem vajadzīgi faili, ko tie vēl nav apstrādājuši.
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
- Glabāšanas termiņš. Rokasgrāmatas noteikums: termiņam jābūt ne mazākam par maksimālo laiku, par kādu replikas var atpalikt. Praksē tam jāaptver arī laiks līdz vecākajai pilnajai rezerves kopijai, no kuras jūs atjaunotu.
- Maiņa darbības laikā.
binlog_expire_logs_secondsir dinamisks. Novecojušie faili tiek dzēsti startējot un tad, kad binārais žurnāls tiek izskalots, tāpēc mazāka vērtība sāk darboties pie nākamās izskalošanas (FLUSH BINARY LOGSprasaRELOADprivilēģiju):
SET PERSIST binlog_expire_logs_seconds = 604800;
FLUSH BINARY LOGS; -- rotācija dod serverim iespēju izdzēst vecos failus
- Saspiešana.
binlog_transaction_compressionpēc noklusējuma ir OFF. Kad tā ir ON, transakciju saturs tiek saspiests ar zstd un paliek saspiests arī replikās un relay žurnālos, ietaupot diska vietu un tīkla datplūsmu. Tas maksā CPU, tāpēc vispirms pārbaudiet to ar savu slodzi. - Veci konfigurācijas faili.
expire_logs_daystika izņemts MySQL 8.2.0. Ja jūsu my.cnf to joprojām iestata, iztīriet to pirms pārejas uz 8.4. - Monitorings. Iestatiet brīdinājumu par binlog direktorijas pieauguma ātrumu, ne tikai par brīvo vietu. Pakešu darbs, kas divkāršo dienas binlog apjomu, ir redzams dienas pirms diska piepildīšanās.
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
- Noklusējuma glabāšanas termiņš ir 30 dienas (
binlog_expire_logs_seconds=2592000), un noslogotam serverim tas bieži ir vairāk, nekā disks spēj ietilpināt. - Pirms dzēšanas atrodiet vecāko
Source_Log_Filestarp visām replikām, arī bezsaistē esošajām, un pārbaudiet, kas vēl vajadzīgs rezerves kopijām un CDC. - Lietojiet
PURGE BINARY LOGS TOvaiBEFORE. Komanda uztur indeksu konsekventu un neizdzēsīs failus, ko lasa pievienota replika. - Nekad nedzēsiet binlog failus ar
rm. Tas sabojā turpmākās dzēšanas, līdz salabojatbinlog.index, un var sabojāt replikas. - Iestatiet glabāšanas termiņu apzināti, apsveriet binlog saspiešanu un sekojiet, cik ātri aug binlog direktorija.