Postgres съдържа хоризонт на движещи се събития, който в действителност е около 2 милиарда транзакции преди или зад текущия идентификатор на транзакцията. Транзакциите с до 2 милиарда пред или с повече от 2 милиарда след текущия идентификатор на транзакция се считат за бъдещи и по този начин ще бъдат невидими за текущите транзакции.
Postgres избягва тази катастрофална загуба на данни, като специално маркира стари редове, така че независимо къде се намират спрямо текущия идентификатор на транзакцията, те ще бъдат видими.
Замразяването е този процес на маркиране на стари живи кортежи (т.е. редове на база данни), така че да не бъдат прегазени от хоризонта на движещите се събития, който иначе би ги направил да изглеждат като в бъдеще. Това е в контраст с вакуумирането, което е освобождаване на пространство, изразходвано от стари мъртви кортежи, които вече не се виждат от никоя транзакция.
И двата процеса се управляват чрез вакуум.
Има редица настройки, които управляват как се извършва замразяването.
Първо, vacuum_freeze_min_age
управлява дали кортежът ще бъде замразен или не, докато vacuum вече разглежда страница, за да види дали има мъртви кортежи, които могат да бъдат почистени. Кортежи, по-стари от vacuum_freeze_min_age
ще бъдат замразени в този случай. Задаването на това ниско означава, че ще има по-малко работа за вършене по-късно, но с възможната цена на допълнителни усилия както при CPU, така и при IO или WAL дейност. Като цяло вероятно искате този комплект за транзакции на стойност поне няколко часа. Да приемем, че очаквате да извършвате до 2000 транзакции в секунда като устойчива скорост. 2000 TPS е 7,2 милиона транзакции на час. По този начин една доста агресивна настройка за този случай може да бъде да кажем 20m. Настройката по подразбиране е 50 м. По същия начин за vacuum_multixact_freeze_min_age
. Имайте предвид, че броячите на транзакция и мултиксид са независими – трябва да ги следите и двата.
Второ, има vacuum_freeze_table_age
и vacuum_multixact_freeze_table_age
. Тези настройки управляват, когато автоматичното вакуумиране не просто ще разглежда страници, които може да имат мъртви редове, но и всяка страница, която може да има размразени редове. По подразбиране за тези настройки са 150 m. Ако сте намалили vacuum_freeze_min_age
достатъчно, в много случаи този по-агресивен вакуум ще има малко или никаква работа. Във всеки случай този процес не е толкова натоварен, колкото преди, тъй като съвременните версии на Postgres (9.6 и по-нови) поддържат карта на страниците, където всички кортежи са замразени, и посещават само онези страници, които не са всички замразени. Това означава, че това вече не е пълно сканиране на таблицата.
Последно има autovacuum_freeze_max_age
. Ако последният път, когато таблицата е била сканирана напълно за незамразени редове, е била повече от това много транзакции преди това, автоматичното вакуумиране ще започне вакуумиране против обвиване на таблицата. По подразбиране е 200 м. По същия начин за autovacuum_multixact_freeze_max_age
за които по подразбиране е 400m. Това е нещо, което наистина искате да избегнете. Има две неща, които могат да се направят. Първо, много често е да се увеличават тези настройки до нещо като 1 милиард, за да си осигурите повече пространство, особено при системи, които са големи потребители на транзакции. Можете да го направите повече, но искате да имате много пространство за транзакции между най-стария си кортеж и хоризонта на събитията. Второ, важно е да наблюдавате системите си и да предприемете коригиращи действия, преди някоя база данни да се сблъска с това. Това коригиращо действие често включва ръчно почистване с прахосмукачка.
Един проблем, който може да възникне, е, когато имате DDL, който кара нормалното (т.е. не против обвиване) автоматично вакуумиране да се анулира. Ако направите това достатъчно, в крайна сметка ще получите принудителен вакуум против обвиване и всеки DDL след това се нарежда на опашка зад процеса на вакуумиране, а това от своя страна блокира всеки по-нататъшен DML. На този етап вашата маса е ефективно нечетлива, докато вакуумът не приключи. Това зависи от модела на използване на вашата база данни, но това не е само теоретична възможност и внедряванията на Postgres и DBA трябва да го вземат предвид.
Мониторингът на вашия клъстер от база данни е от решаващо значение за управлението на това. По-специално трябва да наблюдавате datfrozenxid
и datminmxid
на всяка база данни в клъстера и ако те станат твърде стари, предприемете коригиращи действия, преди да се наложи вакуумиране срещу обвиване. Често проблемът е с една или няколко таблици в базата данни. Кои от тях са проблема, може да се открие чрез разглеждане на relfrozenxid
и relminmxid
от таблиците в базата данни. age()
и mxid_age()
функциите са полезни за откриване на възрастта на идентификатора на транзакцията и съответно броячите на мултиксид.
Замразяването не е нещо, което можете да избегнете, това е основна дейност по поддръжката в Postgres, която трябва да се управлява активно.