Транзакції
22 питань і відповідей у розділі Транзакції.
Питання цього розділу
- Розшифруйте кожну літеру ACID
- Які рівні ізоляції транзакцій існують?
- Що таке Read Uncommitted?
- Що таке Read Committed?
- Що таке Repeatable Read?
- Що таке Serializable?
- Що таке брудне читання (Dirty Read)?
- Що таке неповторюване читання (Non-Repeatable Read)?
- Що таке фантомне читання (Phantom Read)
- Що таке втрачене оновлення (Lost Update)?
- Який рівень ізоляції за замовчуванням в PostgreSQL
- Який рівень ізоляції за замовчуванням в MySQL
- Що таке Propagation в Spring
- Що робить Propagation.NESTED
- В чому різниця між REQUIRED та REQUIRES_NEW
- Що таке анотація @Transactional?
- На якому рівні можна використовувати @Transactional?
- Що таке rollback в транзакціях?
- Які винятки за замовчуванням викликають rollback?
- Як налаштувати rollback для checked винятків?
- Що таке readonly транзакція?
- Що станеться при виклику @Transactional методу з іншого методу того ж класу?
Навігатор по розділу
22 питання для підготовки до співбесіди на Middle Java Developer.
📋 Усі питання
🗺️ Карта залежностей тем
┌──────────────────────────────────────────┐
│ БАЗА ТРАНЗАКЦІЙ (1-2) │
│ 1. ACID │
│ 2. Огляд рівнів ізоляції │
└──────────────────┬───────────────────────┘
│
┌──────────────────────────┼──────────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌────────────────────┐
│ РІВНІ │ │ АНОМАЛІЇ │ │ СУБД-СПЕЦИФІКА │
│ ІЗОЛЯЦІЇ (3-6) │ │ (7-10) │ │ (11-12) │
│ 3. Read Uncom. │ │ 7. Dirty Read │ │ 11. PostgreSQL │
│ 4. Read Comm. │ │ 8. Non-rep. │ │ 12. MySQL │
│ 5. Repeat. R. │ │ 9. Phantom │ │ │
│ 6. Serializable│ │ 10. Lost Update │ │ │
└───────┬───────┘ └───────┬───────┘ └────────┬───────────┘
│ │ │
└────────────────────────┼────────────────────────┘
▼
┌──────────────────────────────────────────┐
│ SPRING TRANSACTION (13-17) │
│ 13. Огляд Propagation │
│ 14. Propagation.NESTED │
│ 15. REQUIRED vs REQUIRES_NEW │
│ 16. @Transactional │
│ 17. Рівні @Transactional │
└──────────────────────────────────────────┘
│
┌────────────────────────┼────────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌────────────────────┐
│ ROLLBACK │ │ СПЕЦІАЛЬНІ │ │ SELF-INVOCATION │
│ (18-20) │ │ (21) │ │ (22) │
│ 18. Rollback │ │ 21. ReadOnly │ │ 22. Self-invocation│
│ 19. Default │ │ │ │ proxy bypass │
│ rollback │ │ │ │ │
│ 20. Custom │ │ │ │ │
│ rollback │ │ │ │ │
└───────────────┘ └───────────────┘ └────────────────────┘
🎯 Рекомендований порядок вивчення
🟢 Рівень Junior (тижні 1-2)
| Крок | Тема | Файли | Мета |
|---|---|---|---|
| 1 | ACID | Q1 | Atomicity, Consistency, Isolation, Durability |
| 2 | Рівні ізоляції | Q2 | 4 рівні, що захищають |
| 3 | Аномалії | Q7, Q8, Q9, Q10 | Dirty Read, Non-repeatable, Phantom, Lost Update |
| 4 | Основи @Transactional | Q16, Q18, Q19 | Що робить, rollback за замовчуванням |
| 5 | PostgreSQL vs MySQL | Q11, Q12 | Рівні за замовчуванням, відмінності |
🟡 Рівень Middle (тижні 3-4)
| Крок | Тема | Файли | Мета |
|---|---|---|---|
| 1 | Read Committed vs Repeatable Read | Q4, Q5 | MVCC vs Next-Key Lock, snapshot timing |
| 2 | Serializable | Q6 | SSI, dependency graph, serialization failure |
| 3 | Propagation | Q13, Q15 | REQUIRED, REQUIRES_NEW, rollback-only mark |
| 4 | NESTED | Q14 | Savepoint, JTA fallback, L1 cache trap |
| 5 | Рівні @Transactional | Q17 | Class vs Method vs Interface |
| 6 | Checked exceptions rollback | Q20 | rollbackFor, noRollbackFor |
| 7 | ReadOnly | Q21 | Dirty checking, replica routing, MVCC hint |
🔴 Рівень Senior (тижні 5-6)
| Крок | Тема | Файли | Мета |
|---|---|---|---|
| 1 | Isolation internals | Q5, Q6 (Senior) | Gap Lock, predicate lock, SSI implementation |
| 2 | Lost Update deep dive | Q10 (Senior) | Write skew, EvalPlanQual, atomic SQL |
| 3 | Propagation mechanics | Q13, Q14, Q15 (Senior) | ThreadLocal, suspend/resume, connection handling |
| 4 | Deadlock scenarios | Q15 (Senior) | REQUIRED + REQUIRES_NEW deadlock timeline |
| 5 | Self-invocation | Q22 | Proxy bypass, exposeProxy, AspectJ |
| 6 | Production scenarios | Q9, Q16 (Senior) | Phantom in batch jobs, checked exception war stories |
🔗 Ключові зв’язки між темами
Тема: Рівні ізоляції та аномалії
Q1 (ACID) → Q2 (Огляд рівнів) → Q3 (Read Uncommitted) → Q4 (Read Committed)
↓ ↓ ↓
Q5 (Repeatable Read) → Q6 (Serializable) Q7 (Dirty Read)
↓ ↓ ↓
Q8 (Non-repeatable Read) → Q9 (Phantom Read) → Q10 (Lost Update)
Ключові зв’язки:
- Q2 ↔ Q7-Q10: Кожен рівень захищає від певних аномалій
- Q4 ↔ Q8: Non-repeatable read виникає саме на Read Committed
- Q5 ↔ Q9: Phantom read запобігається на Repeatable Read (у MySQL через Gap Lock)
Тема: Spring Transaction
Q13 (Propagation) → Q14 (NESTED) → Q15 (REQUIRED vs REQUIRES_NEW)
↓ ↓
Q16 (@Transactional) → Q17 (Рівні) → Q22 (Self-invocation)
Ключові зв’язки:
- Q13 ↔ Q15: Propagation визначає поведінку за наявності зовнішньої транзакції
- Q14 ↔ Q15: NESTED vs REQUIRES_NEW — savepoint vs незалежний commit
- Q16 ↔ Q19: @Transactional rollback лише для RuntimeException + Error
- Q22 ↔ Q13: Self-invocation bypass — проксі не бере участі, propagation не працює
Тема: Rollback та спеціальні налаштування
Q18 (Rollback) → Q19 (Default rollback) → Q20 (Custom rollback)
↓
Q21 (ReadOnly)
Ключові зв’язки:
- Q18 ↔ Q20: rollbackFor перевизначає поведінку за замовчуванням
- Q19 ↔ Q20: Checked exceptions = commit за замовчуванням → rollbackFor = Exception.class
- Q21 ↔ Q18: ReadOnly не робить rollback, але оптимізує читання
🎯 Шпаргалка: що знати для кожного рівня
🟢 Junior
- ACID: Atomicity (все або нічого), Consistency (обмеження виконані), Isolation (не заважають одна одній), Durability (збережено після commit)
- 4 рівні ізоляції: Read Uncommitted, Read Committed, Repeatable Read, Serializable
- Dirty Read = бачу незакомічені дані, Non-repeatable = значення змінилося між SELECT, Phantom = з’явилися/зникли рядки
- PostgreSQL default = Read Committed, MySQL default = Repeatable Read
- @Transactional: rollback для RuntimeException, commit для checked exceptions
🟡 Middle
- Read Committed: snapshot на кожен SELECT → non-repeatable read можливий
- Repeatable Read: snapshot на всю транзакцію → phantom read можливий (у PostgreSQL через MVCC, у MySQL через Gap Lock — запобігається)
- Propagation: REQUIRED (приєднуюсь), REQUIRES_NEW (нова, зовнішня suspend), NESTED (savepoint)
- Self-invocation:
this.method()bypass-ить проксі → @Transactional не працює - ReadOnly: вимикає dirty checking, hint оптимізатору, routing на репліку (якщо налаштовано)
🔴 Senior
- Serializable у PG = SSI (Serializable Snapshot Isolation), не блокує читання, але відкочує при RW-conflict cycles
- Lost Update: atomic SQL (
SET x = x - 1) вирішує проблему без locking - REQUIRES_NEW overhead: suspend ~2ms, new connection ~0.5ms, Session suspend ~2ms, resume ~2ms
- NESTED: не працює з JTA → fallback до REQUIRES_NEW. L1 cache trap після savepoint rollback
- Checked exception rollback: TransactionInterceptor бачить виняток ДО catch → setRollbackOnly() → UnexpectedRollbackException
📝 Формат кожного файлу
Кожен файл містить:
- 🟢 Junior Level — базове розуміння, прості аналогії, приклади
- 🟡 Middle Level — внутрішності, типові помилки, практичні приклади
- 🔴 Senior Level — deep dive, edge cases, production досвід, моніторинг
- 🎯 Шпаргалка для співбесіди — ключові тези, часті питання, червоні прапорці, пов’язані теми