PostgreSQL-də transaksiyalar izolasiya təmin edir — bu, ACID-in əsas xüsusiyyətlərindən biridir. Bunun üçün sistem lock-lardan istifadə edir. Lock — bu, bir neçə transaksiyanın eyni anda eyni sətri və ya cədvəli "ələ keçirməsinin" qarşısını alan mexanizmdir. Təsəvvür elə supermarketdə növbə var: kassada bir nəfər xidmət alır, digərləri gözləyir. Lock-lar da təxminən belə işləyir, sadəcə onlar cədvəldəki məlumatlara girişə nəzarət edir.
Əsas lock növləri
PostgreSQL-də bir neçə lock növü var, bəzilərini sən yəqin ki, artıq EXPLAIN ANALYZE-da görmüsən:
ROW EXCLUSIVE(sətir üçün eksklüziv lock) — sətirdə məlumat dəyişəndə yaranır. Ən çox istifadə olunan lock növüdür, məsələn,INSERT,UPDATEvə yaDELETEzamanı.SHARE(ümumi lock) — sorğu icra olunanda məlumatın dəyişməyəcəyinə zəmanət verir, məsələn,SELECT ... FOR SHAREzamanı.EXCLUSIVE(eksklüziv lock) — məlumat üzərində oxumaqdan başqa bütün əməliyyatların qarşısını alır.
Qısası, lock-lar — bizim məlumatlarımızı qoruyan keşikçi itlər kimidir.
Lock problemi: nə pis ola bilər?
İndi artıq başa düşürük ki, lock nədir, gəlin baxaq, onlar hansı problemlərə səbəb ola bilər. Ən böyüyü — deadlock problemidir. Deadlock — bu, iki (və ya daha çox) transaksiyanın bir-birini gözlədiyi və nəticədə sonsuz dövrə düşdüyü vəziyyətdir. Tipik olaraq belə olur:
- Transaksiya 1 sətir A-nı lock edir və sətir B-yə giriş istəyir.
- Transaksiya 2 sətir B-ni lock edir və sətir A-ya giriş istəyir.
- Hər iki sətir lock olunduğuna görə, heç bir transaksiyanı bitirmək olmur.
Deadlock nümunəsi
Deadlock-la qarşılaşan proqramçının ağrısını hiss etmək üçün belə bir ssenari təsəvvür elə:
-- Transaksiya 1
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- Eyni vaxtda
-- Transaksiya 2
BEGIN;
UPDATE accounts SET balance = balance + 200 WHERE id = 2;
-- Transaksiya 1 id = 2-ni lock etmək istəyir
UPDATE accounts SET balance = balance - 100 WHERE id = 2;
-- Transaksiya 2 id = 1-i lock etmək istəyir
UPDATE accounts SET balance = balance + 200 WHERE id = 1;
Vuala! Hər bir transaksiyanı digəri bloklayır. PostgreSQL bunu gec-tez aşkar edir və deadlock xətası atır.
Deadlock-dan necə qaçmaq olar?
- Məlumatlara ardıcıl giriş qaydası. Həmişə məlumatlara eyni ardıcıllıqla müraciət etməyə çalış. Əgər transaksiya 1 əvvəlcə sətir A-nı, sonra sətir B-ni lock edirsə, transaksiya 2 də eyni qaydaya riayət etməlidir: əvvəlcə sətir A, sonra sətir B.
-- Düzgün giriş ardıcıllığı
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 200 WHERE id = 2;
COMMIT;
Transaksiyaların müddətini minimuma endir. Uzun transaksiyalar deadlock ehtimalını artırır. Transaksiyanı mümkün qədər tez bitir:
BEGIN, bütün lazımi dəyişiklikləri et və dərhalCOMMITelə.Transaksiya izolasiya səviyyələrindən istifadə et. Əgər sənin tapşırığın məlumatların sərt izolasiyasını tələb etmirsə,
READ COMMITTEDizolasiya səviyyəsindən istifadə etməyi düşün. Bu, bəzi lock-lardan qaçmağa imkan verir.
Timeout-lar və lock diaqnostikası
PostgreSQL-də lock-ların diaqnostikası və qarşısını almaq üçün alətlər var. Məsələn, lock üçün maksimum gözləmə vaxtı təyin edə bilərsən:
SET lock_timeout = '5s'; -- Lock üçün timeout-u 5 saniyə təyin edirik
Əgər lock göstərilən vaxtdan çox saxlanılırsa, transaksiya dayandırılır və bu, tam tıxanmanın qarşısını alır.
PostgreSQL-də lock-ların izlənməsi
Lock-ları monitorinq etmək üçün faydalı komandlardan biri pg_locks-dur. Bu, sistemdəki bütün aktiv lock-ları göstərir:
SELECT * FROM pg_locks;
Görə bilərsən ki, hansı transaksiyalar lock saxlayır və hansılar onların açılmasını gözləyir. Xüsusilə deadlock-ları debug edəndə çox kömək edir.
LOCK xüsusiyyətləri və obyektlərin əl ilə bloklanması
Əgər lock-ları əl ilə idarə etmək lazımdırsa, LOCK komandasından istifadə et:
LOCK TABLE orders IN ACCESS EXCLUSIVE MODE;
Diqqət: ACCESS EXCLUSIVE — ən güclü lock-dur, o, cədvəldə hətta SELECT də daxil olmaqla bütün əməliyyatları qadağan edir. Onu yalnız xüsusi hallarda (məsələn, cədvəl strukturunu dəyişəndə) istifadə et.
Sətirləri dəyişəndə onları bloklamaq üçün SELECT ... FOR UPDATE istifadə et:
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
Bu, digər transaksiyaların sənin transaksiyan bitənə qədər bu sətirləri dəyişməsinin qarşısını alır.
Lock-lar haqqında nəyi yadda saxlamaq lazımdır?
Lock-lar — pis şey deyil, alətdir. Onlar məlumatların bütövlüyünü qorumağa kömək edir, amma diqqətli yanaşma tələb edir. Budur bir neçə əsas məsləhət:
- Transaksiyaya başlamamışdan əvvəl, niyə başladığını dəqiq bil.
- Transaksiyanı mümkün qədər tez bitir.
- Məlumatlara fərqli ardıcıllıqla girişdən qaç.
- Tapşırığına uyğun izolasiya səviyyələrindən istifadə et.
İndi sən lock-lar və deadlock-larla işləməyə hazırsan! Qoy pg_locks və ACID-in müdrikliyi səninlə olsun.
GO TO FULL VERSION