Postgres bevat een bewegende gebeurtenishorizon, die in feite ongeveer 2 miljard transacties voor of achter de huidige transactie-ID ligt. Transacties tot 2 miljard voor of meer dan 2 miljard achter de huidige transactie-ID worden beschouwd als toekomstig en zullen dus onzichtbaar zijn voor huidige transacties.
Postgres vermijdt dit catastrofale gegevensverlies door oude rijen speciaal te markeren, zodat ze zichtbaar zijn, ongeacht waar ze zich bevinden ten opzichte van de huidige transactie-ID.
Bevriezen is dit proces van het markeren van oude live-tupels (d.w.z. databaserijen) zodat ze niet worden overreden door de bewegende gebeurtenishorizon waardoor ze anders in de toekomst lijken te zijn. Dit in tegenstelling tot stofzuigen, dat is het vrijmaken van ruimte die wordt verbruikt door oude dode tupels die niet langer zichtbaar zijn voor een transactie.
Beide processen worden beheerd door vacuüm.
Er zijn een aantal instellingen die bepalen hoe het invriezen wordt gedaan.
Ten eerste, vacuum_freeze_min_age
bepaalt of een tuple al dan niet wordt bevroren terwijl vacuüm al naar een pagina kijkt om te zien of deze dode tuples heeft die kunnen worden opgeruimd. Tuples ouder dan vacuum_freeze_min_age
wordt in dit geval bevroren. Als u dit laag instelt, betekent dit dat er later minder werk te doen is, maar dit gaat mogelijk ten koste van extra inspanning, zowel in CPU- als IO- of WAL-activiteit. Over het algemeen wilt u deze set waarschijnlijk op ten minste een paar uur aan transacties. Laten we zeggen dat u verwacht tot 2000 transacties per seconde uit te voeren als een aanhoudende snelheid. 2000 TPS is 7,2 miljoen transacties per uur. Dus een redelijk agressieve instelling voor dit geval zou bijvoorbeeld 20m kunnen zijn. De standaardinstelling is 50 meter. Hetzelfde geldt voor vacuum_multixact_freeze_min_age
. Merk op dat de transaction_id en multixid-tellers onafhankelijk zijn - u moet ze allebei bijhouden.
Ten tweede zijn er vacuum_freeze_table_age
en vacuum_multixact_freeze_table_age
. Deze instellingen bepalen wanneer autovacuüm niet alleen naar pagina's kijkt die mogelijk dode rijen hebben, maar ook voor pagina's met niet-bevroren rijen. De standaardwaarden voor deze instellingen zijn 150m. Als u vacuum_freeze_min_age
. heeft verminderd genoeg, in veel gevallen zal deze agressievere stofzuiger weinig of geen werk te doen hebben. In ieder geval is dit proces niet zo druk als vroeger, aangezien moderne versies van Postgres (9.6 en hoger) een kaart bijhouden van pagina's waar alle tuples zijn bevroren en alleen die pagina's bezoeken die niet allemaal zijn bevroren. Dat betekent dat dit niet langer een volledige tafelscan is.
Als laatste is er autovacuum_freeze_max_age
. Als de laatste keer dat de tafel volledig werd gescand op niet-bevroren rijen meer dan zoveel transacties geleden was, zal autovacuüm een anti-omhullend vacuüm op de tafel starten. De standaard is 200 meter. Hetzelfde geldt voor autovacuum_multixact_freeze_max_age
waarvoor de standaard 400m is. Dit is iets wat je echt wilt vermijden. Er zijn twee dingen die gedaan kunnen worden. Ten eerste is het heel gebruikelijk om deze instellingen te verhogen tot ongeveer 1 miljard, om jezelf meer hoofdruimte te geven, vooral op systemen die veel transacties verbruiken. Je zou er meer van kunnen maken, maar je wilt voldoende transactieruimte hebben tussen je oudste tuple en de gebeurtenishorizon. Ten tweede is het belangrijk om uw systemen in de gaten te houden en corrigerende maatregelen te nemen voordat databases hier tegenaan lopen. Deze herstelactie omvat vaak handmatig stofzuigen.
Een probleem dat zich kan voordoen, is wanneer u DDL heeft dat ervoor zorgt dat het normale (d.w.z. geen anti-omhullende) autovacuüm zichzelf opheft. Als je dit genoeg doet, krijg je uiteindelijk een anti-omhullend vacuüm geforceerd, en elke DDL staat dan in de rij achter het vacuümproces, en dat blokkeert op zijn beurt verdere DML. In dit stadium is uw tafel in feite onleesbaar totdat het vacuüm is afgelopen. Dit hangt af van het gebruikspatroon van uw database, maar dit is niet alleen een theoretische mogelijkheid en Postgres-implementaties en DBA's moeten hier rekening mee houden.
Het bewaken van uw databasecluster is van cruciaal belang om dit te beheren. In het bijzonder moet u de datfrozenxid
. controleren en datminmxid
van elke database in het cluster, en als deze te oud worden, moet u corrigerende maatregelen nemen voordat een anti-omhullend vacuüm vereist is. Vaak ligt het probleem bij een of enkele tabellen in de database. Welke het probleem zijn, kan worden ontdekt door de relfrozenxid
. te onderzoeken en relminmxid
van de tabellen in de database. De age()
en mxid_age()
functies zijn handig om de ouderdom van respectievelijk transactie-ID's en multixid-tellers te ontdekken.
Bevriezen is niet iets dat u kunt vermijden, het is een essentiële onderhoudsactiviteit in Postgres die actief moet worden beheerd.