Incidentu reaģēšana

PostgreSQL transakciju ID wraparound: kā to pamanīt laikus un atgūties

Vispirms brīdinājums, ka datubāze "must be vacuumed within N transactions". Tad rakstīšana apstājas ar "database is not accepting commands". Kā darbojas transakciju ID wraparound, kas patiesībā bloķē VACUUM un kādus atgūšanas soļus šodien iesaka PostgreSQL dokumentācija.

· 12 min lasīšanai · AG Data komanda

PostgreSQL transakciju ID wraparound ir viena no retajām problēmām, kas var apturēt rakstīšanu veselīgi izskatošā datubāzē. Tā nerodas no zila gaisa: nedēļām vai mēnešiem XID vecums aug, tad žurnāls pildās ar WARNING: database "mydb" must be vacuumed within N transactions, un, ja nekas nemainās, PostgreSQL atsakās pieņemt jaunas rakstīšanas transakcijas, lai pasargātu jūsu datus. Labā ziņa ir tā, ka tas ir paredzams, viegli uzraugāms un, ja to pamanāt laikus, pilnībā novēršams.

Kas ir wraparound, vienkāršiem vārdiem

Katra transakcija, kas raksta, saņem transakcijas ID (XID). PostgreSQL izmanto XID, lai noteiktu, kuras rindu versijas katra transakcija redz. XID ir 32 bitu skaitlis, tāpēc, kā skaidro dokumentācija, ID tiek salīdzināti pa apli: jebkuram XID aptuveni divi miljardi ir "pagātnē" un divi miljardi "nākotnē". Ja veca rindas versija saglabātu savu sākotnējo XID ilgāk par diviem miljardiem transakciju, tā pēkšņi izskatītos kā no nākotnes un kļūtu neredzama. Dati joprojām būtu diskā, bet jūs tos neredzētu.

VACUUM to novērš, iesaldējot vecās rindas: atzīmējot tās kā apstiprinātas tik sen, ka tās redz visi, neatkarīgi no skaitītāja. Tātad noteikums ir vienkāršs: katra tabula katrā datubāzē ir jāapstrādā ar VACUUM un tās vecās rindas jāiesaldē vismaz reizi divos miljardos transakciju.

Drošības tīkls un kad tas beidzas

PostgreSQL seko vecākā neiesaldētā XID vecumam katrā tabulā (relfrozenxid) un katrā datubāzē (datfrozenxid):

Pie 200 miljoniem pat noslogota sistēma vēl ir ļoti tālu no problēmām. Šīs atstarpes jēga ir dot autovacuum laiku strādāt. Wraparound incidenti notiek, kad kaut kas ilgstoši neļauj autovacuum šo darbu pabeigt.

1. solis: izmēriet XID vecumu

Katrai datubāzei:

SELECT datname, age(datfrozenxid) AS xid_age,
       round(100.0 * age(datfrozenxid) / 2000000000, 1) AS pct_to_limit
FROM pg_database
ORDER BY xid_age DESC;

Katrai tabulai, ieskaitot TOAST tabulas, balstoties uz dokumentācijas vaicājumu:

SELECT c.oid::regclass AS table_name,
       greatest(age(c.relfrozenxid), age(t.relfrozenxid)) AS xid_age,
       pg_size_pretty(pg_total_relation_size(c.oid)) AS size
FROM pg_class c
LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
WHERE c.relkind IN ('r', 'm')
ORDER BY xid_age DESC
LIMIT 20;

Datubāze, kas pastāvīgi ir virs 200 miljoniem un pēc anti-wraparound vakuumiem nekad nenokrītas, ir modelis, par kuru jāuztraucas. Tas nozīmē, ka vakuumi darbojas, bet nespēj pavirzīt iesaldēšanas robežu, vai dažas milzīgas tabulas nekad netiek pabeigtas.

2. solis: atrodiet, kas aiztur robežu

VACUUM var iesaldēt tikai tās rindas, kas nevienai strādājošai transakcijai vairs nevar būt vajadzīgas. Jebkas, kas uztur dzīvu vecu momentuzņēmumu, notur robežu vecu, lai cik bieži vakuums darbotos. Tipiskie aizdomās turamie ir tieši tie, ko dokumentācija min savos atgūšanas soļos:

-- old transactions
SELECT pid, state, age(backend_xid) AS xid_age, age(backend_xmin) AS xmin_age,
       now() - xact_start AS running_for, left(query, 60) AS query
FROM pg_stat_activity
WHERE backend_xid IS NOT NULL OR backend_xmin IS NOT NULL
ORDER BY greatest(age(backend_xid), age(backend_xmin)) DESC
LIMIT 10;

-- forgotten prepared transactions
SELECT gid, prepared, age(transaction) AS xid_age FROM pg_prepared_xacts;

-- replication slots holding back the horizon
SELECT slot_name, active, age(xmin) AS xmin_age, age(catalog_xmin) AS catalog_xmin_age
FROM pg_replication_slots;

3. solis: ja rakstīšana jau ir apstājusies

Pašreizējā PostgreSQL dokumentācija skaidri saka, ka serveri nevajag apturēt un pāriet vienlietotāja režīmā, kā ieteica vecāki padomi. VACUUM joprojām darbojas normāli. Ieteicamā secība:

  1. Apstipriniet vai atritiniet vecās sagatavotās transakcijas (pg_prepared_xacts).
  2. Pabeidziet ilgstošas atvērtas transakcijas, ja nepieciešams, ar pg_terminate_backend.
  3. Dzēsiet vecus replikācijas slotus, kas pieder serveriem, kuru vairs nav vai kuri ilgi nav darbojušies. Ja dzēšat slotu, ko vēl izmanto dzīva replika, šī replika var būt jāpārbūvē, tāpēc vispirms pārbaudiet.
  4. Palaidiet VACUUM skartajā datubāzē kā superlietotājs, lai tas apstrādātu arī sistēmas katalogus. Vienkāršākais ir VACUUM visai datubāzei; lai ietaupītu laiku, vispirms apstrādājiet tabulas ar vecāko XID vecumu.

No divām lietām jāizvairās: VACUUM FULL vajag jaunu XID, un tas izgāzīsies, bet VACUUM FREEZE veic vairāk darba, nekā vajag, lai atgrieztos darbā. Vienlietotāja režīms ir jēgpilns tikai tad, ja gribat ar DROP vai TRUNCATE noņemt lielas nevajadzīgas tabulas, lai tās nebūtu jāapstrādā ar vakuumu, un tas izslēdz wraparound aizsardzību, tāpēc ir riskantāks.

Klasiska kļūda šī incidenta laikā ir atcelt anti-wraparound autovacuum, jo tas "patērē pārāk daudz I/O" vai bloķē izlaišanu, un pēc tam no nulles sākt manuālu VACUUM uz vairāku terabaitu tabulas. Vispirms noskaidrojiet, kas aiztur robežu; vakuums, kas to nevar pavirzīt, nepalīdzēs, lai cik ātri tas darbotos. Ja rakstīšana produkcijā jau izgāžas, šis ir labs brīdis piesaistīt ārkārtas DBA, nevis apgūt atgūšanas secību zem spiediena.

Kā to novērst

Par ko brīdināt

  1. age(datfrozenxid) katrai datubāzei, ar brīdinājumu ap 500 miljoniem un kritisku brīdinājumu krietni pirms 1 miljarda. Pielāgojiet tam, cik ātri patērējat XID.
  2. Vecākās transakcijas un vecākā backend_xmin vecums pg_stat_activity.
  3. Neaktīvi replikācijas sloti un to xmin vecums.
  4. Jebkurš must be vacuumed within ziņojums žurnālā, kam nekavējoties jāmodina dežurants.
  5. Anti-wraparound autovacuum, kas stundām ilgi darbojas uz vienas tabulas.

Galvenās atziņas

PostgreSQL VACUUM Wraparound Incidentu reaģēšana
Sadarbība ar mums

Redzat wraparound brīdinājumus?

Mēs atrodam, kas bloķē VACUUM, droši samazinām XID vecumu un noskaņojam autovacuum, lai tas neatkārtotos. Pirmā reakcija uz kritiskiem incidentiem 15 minūšu laikā, 24/7.

Sazināties Vairāk no emuāra