sql >> Databasteknik >  >> RDS >> PostgreSQL

Hantera frysning i PostgreSQL

Postgres innehåller en rörlig händelsehorisont, som i själva verket är cirka 2 miljarder transaktioner före eller efter det aktuella transaktions-id:t. Transaktioner upp till 2 miljarder före eller mer än 2 miljarder bakom det aktuella transaktions-ID anses vara i framtiden och kommer därför att vara osynliga för nuvarande transaktioner.

Postgres undviker denna katastrofala dataförlust genom att speciellt markera gamla rader så att oavsett var de befinner sig i förhållande till det aktuella transaktions-id:t kommer de att vara synliga.

Frysning är denna process för att markera gamla levande tupler (dvs databasrader) så att de inte blir överkörda av den rörliga händelsehorisonten som annars skulle få dem att se ut att finnas i framtiden. Detta i motsats till dammsugning, som är att frigöra utrymme som förbrukas av gamla döda tuplar som inte längre är synliga för någon transaktion.

Båda processerna hanteras av vakuum.

Det finns ett antal inställningar som styr hur frysning görs.

Först, vacuum_freeze_min_age styr om en tulpel kommer att frysas eller inte medan vakuum redan tittar på en sida för att se om den har döda tuplar som kan rensas upp. Tuples äldre än vacuum_freeze_min_age kommer att frysas i detta fall. Att sätta detta lågt innebär att det blir mindre arbete att göra senare, men till kostnaden av extra ansträngning både i CPU- och IO- eller WAL-aktivitet. Generellt vill du förmodligen att den här uppsättningen ska ha minst några timmars transaktioner. Låt oss säga att du förväntar dig att göra upp till 2000 transaktioner per sekund som en varaktig takt. 2000 TPS är 7,2 miljoner transaktioner per timme. Så en ganska aggressiv inställning för detta fall kan vara säg 20m. Standardinställningen är 50m. Likadant för vacuum_multixact_freeze_min_age . Observera att transaktions-id och multioxidräknare är oberoende – du måste hålla reda på dem båda.

För det andra finns det vacuum_freeze_table_age och vacuum_multixact_freeze_table_age . Dessa inställningar styr när autovacuum inte bara tittar på sidor som kan ha döda rader, utan alla sidor som kan ha ofrysta rader. Standardinställningarna för dessa inställningar är 150m. Om du har minskat vacuum_freeze_min_age tillräckligt, i många fall kommer detta mer aggressiva vakuum att ha lite eller inget arbete att göra. Hur som helst är den här processen inte lika upptagen som den brukade vara, eftersom moderna versioner av Postgres (9.6 och uppåt) har en karta över sidor där alla tupler är frusna och bara besöker de sidor som inte alla är frusna. Det betyder att detta inte längre är en genomsökning av hela tabellen.

Sist är det autovacuum_freeze_max_age . Om senast bordet skannades fullständigt efter ofrysta rader var mer än så många transaktioner sedan, kommer autovacuum att starta ett anti-wraparound-vakuum på bordet. Standard är 200m. Likadant för autovacuum_multixact_freeze_max_age för vilken standard är 400m. Detta är något du verkligen vill undvika. Det finns två saker som kan göras. För det första är det väldigt vanligt att man ökar dessa inställningar till ungefär 1 miljard, för att ge sig själv mer utrymme, speciellt på system som är storkonsumenter av transaktioner. Du kan göra det mer men du vill ha gott om transaktionsutrymme mellan din äldsta tuppel och händelsehorisonten. För det andra är det viktigt att övervaka dina system och vidta korrigerande åtgärder innan några databaser stöter på detta. Denna avhjälpande åtgärd inkluderar ofta manuell dammsugning.

Ett problem som kan uppstå är när du har DDL som gör att normalt (d.v.s. inte anti-wraparound) autovakuum avbryter sig själv. Om du gör detta tillräckligt så småningom kommer du att tvingas fram ett anti-wraparound-vakuum, och eventuell DDL ställer sig sedan i kö bakom vakuumprocessen, vilket i sin tur blockerar ytterligare DML. I detta skede är ditt bord i praktiken oläsligt tills vakuumet är klart. Detta beror på användningsmönstret för din databas, men detta är inte bara en teoretisk möjlighet och Postgres-distributioner och DBA:er måste ta hänsyn till det.

Att övervaka ditt databaskluster är avgörande för att hantera detta. I synnerhet måste du övervaka datfrozenxid och datminmxid av varje databas i klustret, och om dessa blir för gamla vidta korrigerande åtgärder innan ett anti-wraparound-vakuum krävs. Ofta är problemet med en eller några få tabeller i databasen. Vilka som är problemet kan upptäckas genom att undersöka relfrozenxid och relminmxid av tabellerna i databasen. age() och mxid_age() funktioner är användbara för att upptäcka åldern för transaktions-id respektive multioxidräknare.

Frysning är inget du kan undvika, det är en viktig underhållsaktivitet i Postgres som måste hanteras aktivt.


  1. Höjer ribban för MySQL, MariaDB, PostgreSQL &MongoDB Management

  2. Varför lära sig Cassandra med Hadoop?

  3. Anslutning misslyckades:Åtkomst nekad för användaren 'root'@'localhost' (med lösenord:JA) från php-funktionen

  4. Konfigurera anslutningen mellan klient och server Oracle 10g