JavaRush /Курси /SQL SELF /Типові помилки при роботі з транзакціями

Типові помилки при роботі з транзакціями

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

У цій лекції ми зосередимось на типових помилках, що виникають при роботі з транзакціями, і способах їх уникнення. Повір, навіть найкрутіший SQL-гуру іноді забуває поставити COMMIT! Дамо поради, як зробити помилки в транзакціях рідкістю.

На жаль (або на щастя), бази даних — це не чарівний замок, де все завжди працює ідеально. Помилки в роботі з транзакціями — це досить часте явище, особливо для початківців. Давай розберемо їх детально.

Забута команда COMMIT або ROLLBACK

Забути завершити транзакцію — це справжня "класика жанру". Уяви собі ресторан, де ти замовив страву, але офіціант забув принести чек. У світі PostgreSQL це означає, що база "зависає" в стані транзакції, тримає ресурси і блокує інші операції.

Приклад помилки:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Ой! Ми забули додати COMMIT або ROLLBACK.

Коли транзакція "зависає", блокування ресурсу може поширюватись на всю таблицю. Якщо адміністратор бази знає, що все погано, він може завершити її "жорстко". Але краще до цього не доводити.

Як уникнути?

  • Завжди явно завершуйте транзакцію: COMMIT або ROLLBACK.
  • Використовуйте клієнтські інструменти, які автоматично нагадують про завислі транзакції.
  • Якщо транзакція не завершена, а ти перезапускаєш застосунок, база автоматично зробить ROLLBACK, але це не завжди зручно для стану системи.

Використання неправильного рівня ізоляції

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

Приклад:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
-- Читаємо дані, які змінює інша транзакція
SELECT balance FROM accounts WHERE account_id = 1;
-- Інша транзакція зробить ROLLBACK, і твої дані стануть невалідними.

Як уникнути?

  • Визнач, наскільки важливі дані для твого застосунку.
  • Використовуй READ COMMITTED для більшості сценаріїв, щоб уникнути "брудного" читання.
  • Застосовуй більш суворі рівні ізоляції REPEATABLE READ, SERIALIZABLE для операцій, де критично уникати змін або фантомних даних.

Конфлікт транзакцій і блокування

Іноді дві чи більше транзакцій намагаються змінити одні й ті ж дані. У такому випадку PostgreSQL блокує одну з них, поки інша не завершиться. Це може призвести до ситуації deadlock (взаємного блокування).

Приклад помилки:

-- Перша транзакція
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

-- Друга транзакція
BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 1;
-- Очікування першої транзакції...

Якщо обидві транзакції тримають ресурси, які потрібні одна одній, виникає глухий кут. PostgreSQL знайде deadlock, завершить одну з транзакцій з помилкою і видасть повідомлення:

ERROR: deadlock detected

Як уникнути?

  • Дотримуйся фіксованого порядку виконання операцій у транзакціях.
  • Мінімізуй час виконання транзакції, щоб зменшити ймовірність блокування.
  • Використовуй рівень ізоляції SERIALIZABLE лише коли це дійсно потрібно.

Помилка з SAVEPOINT

SAVEPOINT — крутий інструмент для часткового відкату, але його неправильне використання може призвести до плутанини. Наприклад, якщо ти забув звільнити точку збереження (RELEASE SAVEPOINT), це може призвести до зайвих блокувань або помилок.

Приклад помилки:

BEGIN;
SAVEPOINT my_savepoint;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
ROLLBACK TO SAVEPOINT my_savepoint;
-- Забули звільнити SAVEPOINT!

Як уникнути?

  • Переконайся, що ти видаляєш SAVEPOINT, якщо він більше не потрібен.
  • Старайся не створювати занадто багато точок збереження, щоб не ускладнювати запити.

Несумісність транзакцій із зовнішніми системами

Уяви, що транзакція в PostgreSQL намагається взаємодіяти із зовнішніми системами: надсилання сповіщень, оновлення API тощо. Якщо щось піде не так із зовнішньою системою, відкочувати зміни буде складно.

Приклад:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Не вдається надіслати сповіщення: email-server не відповідає.
COMMIT; -- Зміни збережені, але сповіщення не надіслано.

Як уникнути?

  • По можливості ізолюй операції взаємодії із зовнішніми системами.
  • Використовуй проміжні таблиці або черги задач, щоб координувати дії із зовнішніми системами.

Помилки через великі транзакції

Великі транзакції, які містять багато операцій, мають тенденцію бути більш вразливими до помилок: блокувань, таймаутів і deadlock'ів.

Приклад:

BEGIN;
-- Кілька тисяч операцій оновлення
UPDATE orders SET status = 'completed' WHERE delivery_date < CURRENT_DATE;
COMMIT; -- Може зайняти багато часу.

Як уникнути?

  • Діли великі транзакції на кілька менших.
  • Використовуй batch'і для оновлення даних.
  • Мінімізуй обсяг даних, які змінюються в межах однієї транзакції.

Забута перевірка помилок

Не всі SQL-запити в транзакції можуть пройти успішно. Наприклад, якщо одна з операцій видає помилку, вся транзакція опиниться у стані провалу.

Приклад:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = -1; -- Помилка: account_id не існує.
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT; -- Не виконується через помилку.

Як уникнути?

  • Завжди перевіряй результат виконання кожної операції.
  • Використовуй обробку помилок у своїх запитах або клієнтському коді.

Неправильне розуміння поведінки ROLLBACK

Багато розробників думають, що ROLLBACK скасовує зміни і повертає все у вихідний стан. Але ROLLBACK працює тільки в межах поточної транзакції.

Приклад помилкового уявлення:

UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
ROLLBACK; -- Помилка! Це не працює, бо операція не була в транзакції.

Як уникнути?

  • Пам'ятай: BEGIN — твій друг, а без нього ROLLBACK безсилий.
  • Завжди обгортуй критичні операції в транзакції.
1
Опитування
Вступ до рівнів ізоляції транзакцій, рівень 40, лекція 4
Недоступний
Вступ до рівнів ізоляції транзакцій
Вступ до рівнів ізоляції транзакцій
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ