Упражнение 1: Основы обработки транзакций
Задача:
Напишите транзакцию, которая переводит $200 с аккаунта 1 на аккаунт 2. Убедитесь, что транзакция является атомарной, то есть если какая-либо часть ее не выполнится, изменения не должны быть зафиксированы в базе данных.
Упражнение 2: Обработка ошибок в транзакциях
Задача:
Напишите транзакцию, которая пытается перевести $5000 с аккаунта 1 на аккаунт 3, но у аккаунта 1 недостаточно средств. Убедитесь, что транзакция откатывается в случае ошибки.
Упражнение 3: Уровни изоляции и конкурентность
Задача:
На уровне изоляции SERIALIZABLE
создайте две конкурентные транзакции, которые изменяют баланс одного и того же аккаунта. Опишите, как PostgreSQL обрабатывает эту ситуацию.
Упражнение 4: Точки сохранения
Задача:
Создайте транзакцию, которая использует точку сохранения (savepoint) для частичного отката неудачной операции, сохраняя при этом результаты операций до точки сохранения.
Упражнение 5: Обнаружение и разрешение взаимных блокировок
Задача:
Организуйте ситуацию взаимной блокировки между двумя транзакциями и продемонстрируйте, как PostgreSQL обнаруживает и разрешает ее.
Упражнение 6: Транзакция с несколькими таблицами
Используйте ту же таблицу "accounts". Добавьте новую таблицу с именем "transfers", содержащую следующие столбцы:
CREATE TABLE transfers ( id SERIAL PRIMARY KEY, from_account_id INTEGER REFERENCES accounts(id), to_account_id INTEGER REFERENCES accounts(id), amount DECIMAL(10, 2) );
Задача: Напишите транзакцию, которая переводит $200 с аккаунта 1 на аккаунт 2 и вставляет запись об это переводе в таблицу "transfers".
Упражнение 3
Если PostgresSQL обнаруживает, что одна из транзакций конфликтует с другой и обе из них serializable, он убивает одну из них, выводя подобный лог:
ERROR: could not serialize access due to concurrent update
Лог из контейнера с программой делающей запросы:
python_container | В задаче три была выполнена только одна транзакция
Упражнение 4 Посмотрим на лог из контейнера с базой данных
ERROR: deadlock detected
DETAIL: Process 72 waits for ShareLock on transaction 746; blocked by process 71.
Process 71 waits for ShareLock on transaction 747; blocked by process 72.
Process 72:
UPDATE accounts
SET balance = balance + 200
WHERE account_id = 1;
Process 71:
UPDATE accounts
SET balance = balance + 200
WHERE account_id = 2;
CONTEXT: while updating tuple (0,8) in relation "accounts"
STATEMENT:
UPDATE accounts
SET balance = balance + 200
WHERE account_id = 1;
Потсгрес обнаруживает дедлок и убивает одну из транзакций, что видно по логу из программы отправляющей запросы:
python_container | Выполнилась лишь одна из операций, вызвавших дедлок