JavaRush /Курси /SQL SELF /Вступ до рівнів ізоляції транзакцій

Вступ до рівнів ізоляції транзакцій

SQL SELF
Рівень 39 , Лекція 4
Відкрита

Уяви, що ти працюєш у кафе, де один офіціант перевіряє запас тортів на кухні, а інший оформлює замовлення на торт від нового клієнта. В ідеальному світі вони обидва мають працювати з однаковими даними про кількість тортів, щоб уникнути фейлів типу "подвійного бронювання". Але в реальному світі можуть виникати проблеми паралельного виконання операцій.

Ось три основні неприємності, які можуть трапитись:

  1. Dirty Read (брудне читання): Один запит бачить зміни, які зроблені іншим, але ще не підтверджені. Якщо ці зміни відкочуються, перший запит виглядає наївно, як студент на першій співбесіді.

  2. Non-Repeatable Read (неповторюване читання): Один запит двічі читає ті самі дані, але між цими читаннями хтось інший встигає їх змінити. Це як прийти на вокзал, глянути на розклад потягів, повернутись за хвилину — і побачити, що потяг скасували. Або твій квиток купили, поки ти шукав гроші :)

  3. Phantom Read (фантомне читання): Один запит бачить підмножину рядків, але між двома виконаннями хтось додає нові рядки, які впливають на результат. Це якби твоя компанія програла тендер, а потім всі заявки, крім твоєї і заявки дружини мера, скасували.

Рівні ізоляції транзакцій

Тепер, коли ми знаємо про проблеми, час глянути на інструмент, який PostgreSQL дає для їх вирішення — рівні ізоляції транзакцій. Це як встановлення правил для взаємодії між паралельними транзакціями. Чим вищий рівень ізоляції, тим більше гарантій, що транзакції не будуть одна одній заважати. Але за це доведеться платити зниженням "швидкості обслуговування", тобто продуктивністю.

Рівні ізоляції у PostgreSQL

  1. Read Uncommitted (Читання непідтверджених даних):

    • Дозволяє читати зміни, які ще не були підтверджені (так, це брудне читання у всій красі).
    • У PostgreSQL цей рівень насправді реалізований як Read Committed, тобто в чистому вигляді не підтримується. PostgreSQL відмовляється його реалізовувати, бо цей підхід занадто ненадійний.
  2. Read Committed (Читання підтверджених змін):

    • Запобігає брудному читанню.
    • Транзакція бачить тільки ті дані, які були підтверджені на момент виконання її команди.
    • Але можливі Non-Repeatable Read і Phantom Read.
  3. Repeatable Read (Повторюване читання):

    • Гарантує, що дані, які ти читаєш, залишаться незмінними під час транзакції.
    • Запобігає брудному читанню і неповторюваному читанню.
    • Але фантомні рядки все ще можливі.
  4. Serializable (Серіалізований):

    • Гарантує, що транзакції виконуються так, ніби вони виконуються послідовно, одна за одною.
    • Запобігає всім трьом проблемам: брудному читанню, неповторюваному читанню і фантомним рядкам.
    • Найсуворіший — і найповільніший — рівень ізоляції.

Чому ізоляція транзакцій важлива?

Уяви базу даних інтернет-магазину, де тисяча користувачів одночасно намагаються оформити замовлення. Без грамотно налаштованого рівня ізоляції можна зловити купу конфліктів: від "зниклих" товарів до дубльованих замовлень.

Вибір потрібного рівня ізоляції допомагає впоратись з конкурентним виконанням транзакцій, забезпечуючи баланс між продуктивністю і цілісністю даних. Наприклад:

  • В аналітичних системах частіше обирають мінімальні рівні ізоляції (наприклад, Read Committed), бо точність даних не завжди критична.
  • У фінансових системах краще використовувати рівень Serializable, щоб уникнути помилок у розрахунках чи дублювання операцій.

Приклади застосування рівнів ізоляції

  1. Read Committed

Цей рівень гарантує, що ти ніколи не прочитаєш дані, які могли бути відкочені.

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;

-- Прочитати дані рахунку.
SELECT balance FROM accounts WHERE account_id = 1;

-- Якщо інша транзакція оновить баланс, ці дані одразу оновляться.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;
  1. Repeatable Read

Цей рівень гарантує, що якщо ти читаєш дані, вони залишаться незмінними для тебе протягом транзакції.

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;

-- Прочитати дані рахунку.
SELECT balance FROM accounts WHERE account_id = 1;

-- Навіть якщо інша транзакція оновить цей баланс, ти не побачиш зміни.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;
  1. Serializable

На цьому рівні транзакція працює так, ніби вона єдина у системі.

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;

-- Прочитати дані рахунку.
SELECT balance FROM accounts WHERE account_id = 1;

-- Будь-яка інша транзакція, яка намагається змінити ці дані, буде заблокована до завершення твоєї транзакції.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;

Як обрати рівень ізоляції?

Вибір рівня ізоляції залежить від твоїх вимог:

  • Якщо швидкість важливіша за точність, і ти готовий миритись з фантомними рядками — обирай Read Committed.
  • Якщо точність важлива, але ти все ще хочеш зберегти високу продуктивність — використовуй Repeatable Read.
  • Якщо тобі потрібна 100% гарантія коректності даних, навіть на шкоду швидкості — тобі підходить Serializable.

Будь обережний! Суворі рівні ізоляції можуть призвести до блокувань і зниження продуктивності системи. Розумне рішення — компроміс між продуктивністю і узгодженістю даних.

1
Опитування
Вступ до транзакцій, рівень 39, лекція 4
Недоступний
Вступ до транзакцій
Вступ до транзакцій
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ