CodeGym /Kurslar /SQL SELF /Məlumatların bütövlüyünü təmin etmək üçün transaction-lar...

Məlumatların bütövlüyünü təmin etmək üçün transaction-larla işləmək

SQL SELF
Səviyyə , Dərs
Mövcuddur

Gəlin təsəvvür edək ki, sən online mağaza üçün tətbiq yazırsan və sifarişin ödənişi zamanı sənə bunları etmək lazımdır:

  1. Müştərinin kartından pulu bloklamaq.
  2. Anbarda məhsulun sayını azaltmaq.
  3. Uğurlu transaction haqqında qeyd yaratmaq.

Bəs bu addımların ortasında nəsə səhv getsə nə olacaq? Məsələn, pul artıq bloklanıb, amma məhsul anbarda qurtarıb və sifariş haqqında qeyd yaradılmayıb? Hər şey alt-üst olacaq: pul "havada qalıb", sifariş tamamlanmayıb, serverinə isə tonlarla əsəbi məktub (bəlkə də məhkəmə iddiaları) gəlir.

Transaction-lar məhz belə situasiyalardan qaçmağa kömək edir. Onlar bir neçə əməliyyatı bir "atomik" iş vahidinə birləşdirməyə imkan verir. Bu, sanki mətn redaktorunda "Geri al" düyməsidir: nəsə səhv getsə, sadəcə əvvələ qayıdırsan.

Transaction-lar məlumatların bütövlüyünü necə təmin edir?

Transaction-lar ACID konsepsiyasına əsaslanır:

  • Atomiklik (Atomicity) — Transaction daxilindəki bütün əməliyyatlar ya tam yerinə yetirilir, ya da heç biri. "Ya hamısı, ya heç nə".
  • Uyğunluq (Consistency) — Məlumatlar transaction-dan əvvəl və sonra uyğun vəziyyətdə qalır.
  • İzolyasiya (Isolation) — Bir transaction digərinə mane olmur.
  • Davamlılıq (Durability) — Transaction bitəndə, nəticə hətta sistem çökəndə də saxlanılır.

Niyə bunu yenə təkrar edirəm? Çünki bu, hamının can atdığı idealdır. Və... demək olar ki, heç vaxt tam əldə olunmur. Kursda transaction-lara ikinci dəfə qayıdanda görəcəksiniz ki, bəzi ACID prinsiplərindən imtina etməli olacağıq.

Ona görə də, transaction-lar hələ bu qədər sadə və gözəl olanda zövq alın. Və gəlin artıq nümunələrə keçək!

Transaction-lardan istifadə nümunəsi

Gəlin tələbə əlavə edib onu kursa qeydiyyatdan keçirmə ssenarisinə baxaq.

Tutaq ki, universitetin məlumat bazası ilə işləyirik. Kurslarımıza əlavə dinləyicilər gəlib. Əgər kursda yer varsa, belə dinləyicini (müvəqqəti) tələbə kimi qeydiyyatdan keçiririk və kursa əlavə edirik. Bu, belə baş verəcək.

Yeni tələbəni bazaya əlavə edib onu kursa qeydiyyatdan keçirəndə bunları etmək lazımdır:

  1. students cədvəlinə qeyd əlavə etmək.
  2. Tələbəni kursla birləşdirən enrollments cədvəlində qeyd yaratmaq.

Nəsə səhv getsə (məsələn, kurs artıq dolubsa), əməliyyatı geri qaytarmalıyıq ki, məlumatlar cədvəllər arasında uyğunsuz olmasın. Bu, belə edilir:

-- Transaction başlanğıcı
BEGIN;

-- Addım 1: Tələbəni əlavə edirik
INSERT INTO students (name, age, gender)
VALUES ('Otto Lin', 20, 'Male')
RETURNING id;

-- Tutaq ki, id = 10 qaytarıldı

-- Addım 2: Onu kursa qeydiyyatdan keçiririk
INSERT INTO enrollments (student_id, course_id)
VALUES (10, 5);

-- Hər şey uğurla keçdi? Dəyişiklikləri təsdiqləyirik
COMMIT;

Səhv baş verəndə nə olur?

Birdən kursa qeydiyyatda səhv baş verdi: məsələn, kurs mövcud deyil. Əgər transaction-u unutsan, students cədvəlində tələbə haqqında qeyd qalacaq, amma enrollments cədvəlində olmayacaq. Bu, məlumatların bütövlüyünü pozur. Bunu önləmək üçün ROLLBACK komandasından istifadə edə bilərik.

-- Transaction başlanğıcı
BEGIN;

-- Addım 1: Tələbəni əlavə edirik
INSERT INTO students (name, age, gender)
VALUES ('Otto Lin', 20, 'Male')
RETURNING id;

-- Addım 2: Onu kursa qeydiyyatdan keçirməyə çalışırıq
INSERT INTO enrollments (student_id, course_id)
VALUES (10, 999); -- Səhv: id = 999 olan kurs yoxdur!

-- Bütün dəyişiklikləri geri qaytarırıq
ROLLBACK;

Nəticədə heç bir əməliyyat yerinə yetirilməyəcək və məlumat bazası transaction-dan əvvəlki vəziyyətdə qalacaq.

SAVEPOINT ilə idarəetmə

İndi isə daha çətin ssenari təsəvvür edək. Bir neçə əməliyyat etmək istəyirsən, amma hansısa mərhələdə yalnız müəyyən bir nöqtəyə qədər geri qayıtmaq lazımdır, bütün prosesi yox.

Gəlin tələbənin addım-addım qeydiyyatını həyata keçirək

-- Transaction başlanğıcı
BEGIN;

-- Tələbəni əlavə edirik
SAVEPOINT add_student; -- Yaddaş nöqtəsi yaradırıq
INSERT INTO students (name, age, gender)
VALUES ('Anna Song', 22, 'Female');

-- Onu birinci kursa qeydiyyatdan keçiririk
SAVEPOINT enroll_course_1; -- Daha bir yaddaş nöqtəsi
INSERT INTO enrollments (student_id, course_id)
VALUES (11, 5);

-- Onu ikinci kursa qeydiyyatdan keçiririk (burada səhv)
INSERT INTO enrollments (student_id, course_id)
VALUES (11, 999); -- Səhv!

-- Yalnız son yaddaş nöqtəsinə qədər geri qayıdırıq
ROLLBACK TO enroll_course_1;

-- Prosesi davam etdiririk
INSERT INTO enrollments (student_id, course_id)
VALUES (11, 6);

-- Dəyişiklikləri təsdiqləyirik
COMMIT;

Beləliklə, prosesin bir hissəsindəki səhvlər digər hissələrdə məlumatların saxlanmasına mane olmur.

Dəyişikliklərin olub-olmadığını yoxlamaq

Əgər SQL sorğusu nəyisə dəyişirsə, həqiqətən dəyişiklik olub-olmadığını yoxlamaq mümkündür.

Axı belə vəziyyət ola bilər ki, DELETE etmişik, amma WHERE-ə heç bir sətr düşməyib. Və ya UPDATE etmişik, amma məlumatlar artıq dəyişib və faktiki heç nə dəyişməyib.

Bu halda xüsusi sistem dəyişəni FOUND var. O göstərir ki, son SQL sorğusunda sətrlər təsirləndimi:

  • FOUND = TRUE — sorğu nəyisə yenilədi/sildi;
  • FOUND = FALSE — heç nə silinməyib və ya dəyişməyib.

Adi SELECT-lə işləmir, yalnız dəyişiklikləri izləmək üçündür.

Praktik tətbiq: ödənişlərin işlənməsi

Transaction-lar xüsusilə maliyyə tətbiqlərində faydalıdır. Gəlin yenə bir hesabdan digərinə pul köçürən sistemə baxaq.

-- Transaction başlanğıcı
BEGIN;

-- Addım 1: Birinci hesabdan pul çıxırıq
UPDATE accounts
SET balance = balance - 100
WHERE id = 1 AND balance >= 100;

-- Addım 2: Əməliyyat uğurludurmu (sətrlər dəyişibmi) yoxlayırıq
IF NOT FOUND THEN
    ROLLBACK; -- Əgər vəsait çatmırsa, geri qaytarırıq
    RAISE EXCEPTION 'Vəsait çatışmır!'; -- Səhv! İstisna atırıq
END IF;

-- Addım 3: İkinci hesaba pul əlavə edirik
UPDATE accounts
SET balance = balance + 100
WHERE id = 2;

-- Transaction-u təsdiqləyirik
COMMIT;

Burada, əgər müştəri hesabında olandan çox pul köçürməyə çalışsa, transaction geri qaytarılacaq və məlumat bazası "havada" qalmayacaq.

Xüsusiyyətlər və tipik səhvlər

COMMIT unudulub: transaction-un sonunda COMMIT etməyi unutsan, məlumat bazası "gözləmə rejimində" qalacaq və dəyişikliklər saxlanmayacaq.

WHERE unudulub: şərtsiz məlumat yeniləmə və ya silmə fəlakətli nəticələrə səbəb ola bilər. Məsələn, DELETE FROM students WHERE olmadan bütün tələbələri siləcək.

Uzun transaction-lar: transaction çox uzun açıq qalarsa, məlumatlara çıxışı bloklaya bilər və bu da performans problemlərinə gətirib çıxarar. Həmişə transaction-ları (COMMIT və ya ROLLBACK) mümkün qədər tez bitirin.

Transaction-lar — məlumatların bütövlüyünü təmin edəndə sənin yeganə dostundur. Onlar uyğunsuzluqdan qaçmağa kömək edir, xüsusilə mürəkkəb ssenarilərdə, məsələn, istifadəçi qeydiyyatı, ödənişlərin işlənməsi və ya əlaqəli cədvəllərin yenilənməsi. BEGIN, COMMIT, ROLLBACKSAVEPOINT komandalarını mənimsədikdən sonra daha etibarlı və təhlükəsiz tətbiqlər yarada biləcəksən.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION