PostgreSQL Antipatterns: "ölülər" qoşunları ilə mübarizə

PostgreSQL-in daxili mexanizmlərinin özəllikləri onun bəzi hallarda çox sürətli, digərlərində isə “çox sürətli olmamasını” təmin edir. Bu gün biz DBMS-nin necə işlədiyi və tərtibatçının onunla nə etdiyi arasındakı ziddiyyətin klassik nümunəsinə diqqət yetirəcəyik - UPDATE vs MVCC prinsipləri.

Qısa hekayədən əla məqalə:

Sətir UPDATE əmri ilə dəyişdirildikdə, əslində iki əməliyyat yerinə yetirilir: DELETE və INSERT. IN sətirin cari versiyası xmax YENİLƏNMƏni həyata keçirən əməliyyatın sayına bərabər təyin edilir. Sonra yaradılır yeni versiya eyni xətt; onun xmin dəyəri əvvəlki versiyanın xmax dəyəri ilə üst-üstə düşür.

Bu əməliyyatın tamamlanmasından bir müddət sonra köhnə və ya yeni versiyaya bağlıdır COMMIT/ROOLBACK, tanınacaq "ölü" (ölü tuples) keçəndə VACUUM cədvələ uyğun olaraq və təmizlənir.

PostgreSQL Antipatterns: "ölülər" qoşunları ilə mübarizə

Ancaq bu dərhal baş verməyəcək, ancaq "ölü" ilə bağlı problemlər çox tez əldə edilə bilər - təkrarlanan və ya qeydlərin kütləvi yenilənməsi böyük bir masada və bir az sonra eyni vəziyyətlə qarşılaşacaqsınız VAKUUM kömək edə bilməyəcək.

# 1: Mən onu köçürməyi xoşlayıram

Deyək ki, sizin metodunuz biznes məntiqi üzərində işləyir və birdən anlayır ki, hansısa qeyddə X sahəsini yeniləmək lazım olacaq:

UPDATE tbl SET X = <newX> WHERE pk = $1;

Sonra, icra irəlilədikcə, Y sahəsinin də yenilənməli olduğu ortaya çıxır:

UPDATE tbl SET Y = <newY> WHERE pk = $1;

... və sonra da Z - niyə xırda şeylərə vaxt sərf edirsiniz?

UPDATE tbl SET Z = <newZ> WHERE pk = $1;

İndi verilənlər bazasında bu qeydin neçə versiyası var? Bəli, 4 ədəd! Bunlardan biri uyğundur və 3-ü sizdən sonra [avtomatik]VAKUUM vasitəsi ilə təmizlənməlidir.

Bunu belə etməyin! istifadə edin bir sorğuda bütün sahələrin yenilənməsi — demək olar ki, həmişə metodun məntiqi belə dəyişdirilə bilər:

UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;

# 2: İstifadə FƏRQDİR, Luka!

Deməli, hələ də istəyirdin cədvəldə çoxlu, çoxlu qeydləri yeniləyin (məsələn, skript və ya çeviricinin istifadəsi zamanı). Və bu kimi bir şey skriptə uçur:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;

Təxminən bu formada sorğu olduqca tez-tez baş verir və demək olar ki, həmişə boş bir yeni sahəni doldurmaq üçün deyil, məlumatlardakı bəzi səhvləri düzəltmək üçün baş verir. Eyni zamanda, o, özü mövcud məlumatların düzgünlüyü ümumiyyətlə nəzərə alınmır - amma boş yerə! Yəni, orada tam olaraq tələb olunan şey olsa belə, rekord yenidən yazılır - bəs niyə? Gəlin düzəldək:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;

Bir çox insanlar belə bir gözəl operatorun mövcudluğundan xəbərdar deyillər, buna görə də burada bir fırıldaqçı vərəq var IS DISTINCT FROM və digər məntiqi operatorlar kömək edir:
PostgreSQL Antipatterns: "ölülər" qoşunları ilə mübarizə
... və kompleks üzərində əməliyyatlar haqqında bir az ROW()-ifadələri:
PostgreSQL Antipatterns: "ölülər" qoşunları ilə mübarizə

#3: Mən sevgilimi... blok etməklə tanıyıram

istifadəyə verilir iki eyni paralel proses, hər biri girişi "davam edir" kimi qeyd etməyə çalışır:

UPDATE tbl SET processing = TRUE WHERE pk = $1;

Bu proseslər əslində bir-birindən asılı olmayan, lakin eyni identifikator daxilində işlər görsə belə, birinci əməliyyat tamamlanana qədər ikinci müştəri bu sorğuya “bağlı olacaq”.

Həll # 1: tapşırıq əvvəlkinə endirilir

Gəlin onu yenidən əlavə edək IS DISTINCT FROM:

UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;

Bu formada ikinci sorğu sadəcə verilənlər bazasında heç nəyi dəyişməyəcək, hər şey artıq olması lazım olduğu kimidir - buna görə də bloklama baş verməyəcək. Sonra, tətbiq olunan alqoritmdə qeydin "tapılmaması" faktını emal edirik.

Həll # 2: məsləhət kilidləri

Haqqında oxuya biləcəyiniz ayrı bir məqalə üçün böyük bir mövzu tətbiq üsulları və tövsiyyə blokunun “rake”.

Həll # 3: axmaq zənglər

Ancaq bu sizin başınıza gəlməli olan şeydir eyni rekordla eyni vaxtda işləmək? Yoxsa, məsələn, müştəri tərəfində biznes məntiqinə zəng etmək üçün alqoritmləri qarışdırdınız? Və bu barədə düşünsəniz?..

Mənbə: www.habr.com

Добавить комментарий