Postgres – vsetko, co si chtel vediet, ale bal sa spytat svojho seniora, aby si nevypadal ako jelito 05. Locky.
Zamky su normalna vec na vynucovanie transakcnej izolacie (ACID). Pokial sa vam nechce citat toto, ale original, tak tu docu na Postgres. Info o zamkoch zhromazduje systemova tabulka pg_locks
.
Explicit locks
Existuju zamky na urovni tabulky (table lock) a na urovni riadkov (row lock). Z povahy veci vyplyva, ze pri DDL sa bude jednat prevazne o table lock a pri DML o row lock. (Existuje aj page lock, ale neviem, co to je a advisory lock, coz su nepovinne nesystemove locky, pre pripad, ze ich aplikacia chce.).
Table lock sa objavi/neobjavi pri tychto udalostiach, vid tabulka:
Row lock zase pri tychto prilezitostiach:
Malokto si samozrejme zapamata takuto tabulku z hlavy, pre prakticke pouzitie si vacsinou staci zapamatat 2 druhy lockov: “shared” locks (zamknuta entita je neajkym sposobom dostupna pre ine procesy, napr. len pre citanie) a “exclusive” locks (ako nazov indikuje, je to ekskluzivne). Typicky vznikaju exclusive locks pri: vacuu/autovacuu, create index, alter table.
Deadlocks
Deadlocky su zamky, kde jeden proces caka na datovu strukturu, obsadenu inym procesom a ten iny proces caka na ten prvy proces (proste sa navzajom blokuju). Deadlocky riesi Postgres sam – pokial ich detekuje, tak zhodi procesy a odroluje transakcie. Myslim, ze Postgres 11 to urobi do 1s od detekcie deadlocku, ale default sa da zmenit v postgresql.conf (deadlock_timeout =…) . Dokumentacia Postgresu uvadza skutocne kniezaciu radu, ako s deadlockom obcovat: “The best defense against deadlocks is generally to avoid them”…
Logovanie, nastavenie
Je pomerne mudre logovat dlhsie locky, pretoze rezia logovania je velmi nizka.
Typy a triky na locky a performance
Problematicke su hlavne table locks u velkych databazi, pretoze vlastne DB odstrelia (nemozne cokolvek aj po niekolko hoidn), takze bacha.
1. Pridavanie stlpce – nikdy s default value, pretoze kym tu default value prepise do vsetkych milionov riadkov, tak zamyka celu tabulku. Takze lepsie novy stlpec prazdny a potom ho updatovat.
ALTER TABLE news ADD COLUMN last_update timestamptz DEFAULT now(); NIE!!!!
ALTER TABLE news ADD COLUMN last_update timestamptz; UPDATE news SET last_update = now(); DOBRE!!!!
2. Pokial mas velku tabulku a spustas DDL, je dobrou praxou dat timeout na locky – pre pripad, ze by to trvalo dlho. Transakcia sic enedobehne, ale clovek sa nevylockuje a moze to premysliet a urobit inak.
SET lock_timeout TO '2s'
ALTER TABLE news ADD COLUMN last_update timestamptz;
3. Indexy. Pri vytvarani indexov sa tabulka vzdy lockne pre writy (nie pre ready). Pokial je tabulka fakt velka, nie je vynimkou budovanie indexu niekolko hodin. Preto je lepsie robit ich concurrently. Ma to tu nevyhodu, ze pokial se index nedobuduje, tak sa po pade neodroluje je ciastocny – nutne ho rucne vymazat a spustit znovu.
CREATE INDEX CONCURRENTLY news_date_idx ON items USING GIN (value varchar);