[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-postgresql-chto-takoe-deadlock-i-kak-ego-izbezhat":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":15,"progress":16,"seo":17},1046,"chto-takoe-deadlock-i-kak-ego-izbezhat",28,"postgresql","PostgreSQL","🐘","Что такое deadlock и как его избежать?","Deadlock (взаимная блокировка) — ситуация, когда две или более транзакции блокируют друг друга, каждая ожидая ресурс, удерживаемый другой. PostgreSQL автоматически обнаруживает deadlock и откатывает одну из транзакций.\n\n### Пример\n\n```\nТранзакция 1:                        Транзакция 2:\nBEGIN;                               BEGIN;\nUPDATE accounts SET balance = 900    UPDATE accounts SET balance = 1100\n  WHERE id = 1;  -- блокирует id=1    WHERE id = 2;  -- блокирует id=2\nUPDATE accounts SET balance = 1100   UPDATE accounts SET balance = 900\n  WHERE id = 2;  -- ЖДЁТ id=2         WHERE id = 1;  -- ЖДЁТ id=1\n-- DEADLOCK!\n```\n\nPostgreSQL обнаруживает deadlock через детектор с периодом `deadlock_timeout` (по умолчанию 1 секунда) и откатывает одну из транзакций с ошибкой `ERROR: deadlock detected`.\n\n### Способы избежать deadlock\n\n**1. Единый порядок обращения к ресурсам:**\n```sql\nBEGIN;\nUPDATE accounts SET balance = balance - 100 WHERE id = LEAST(1, 2);\nUPDATE accounts SET balance = balance + 100 WHERE id = GREATEST(1, 2);\nCOMMIT;\n```\n\n**2. SELECT FOR UPDATE с сортировкой:**\n```sql\nBEGIN;\nSELECT * FROM accounts WHERE id IN (1, 2) ORDER BY id FOR UPDATE;\nUPDATE accounts SET balance = balance - 100 WHERE id = 1;\nUPDATE accounts SET balance = balance + 100 WHERE id = 2;\nCOMMIT;\n```\n\n**3. Минимизировать время транзакций** — не выполнять долгие вычисления или вызовы внешних сервисов внутри транзакции.\n\n**4. NOWAIT или SKIP LOCKED:**\n```sql\nSELECT * FROM accounts WHERE id = 1 FOR UPDATE NOWAIT;\nSELECT * FROM task_queue WHERE status = 'pending'\nORDER BY id LIMIT 1 FOR UPDATE SKIP LOCKED;\n```\n\n**5. Уменьшить уровень изоляции** — `READ COMMITTED` менее склонен к deadlock, чем `SERIALIZABLE`.\n\n> **На собеседовании:** главное правило предотвращения deadlock — единый порядок обращения к ресурсам. Если все транзакции блокируют строки в порядке возрастания ID, deadlock невозможен. Упомяните, что PostgreSQL обнаруживает deadlock автоматически, поэтому приложение должно уметь повторять откаченную транзакцию.","","middle",[7],[],null,{"title":18,"description":19,"ogTitle":18,"ogDescription":20,"keywords":21,"schemaAnswer":22,"featuredSnippetReady":23},"Что такое deadlock и как его избежать? — Gymterview","Deadlock (взаимная блокировка) — ситуация, когда две или более транзакции блокируют друг друга, каждая ожидая ресурс, удерживаемый другой. PostgreSQL автоматиче","Deadlock (взаимная блокировка) — ситуация, когда две или более транзакции блокируют друг друга, каждая ожидая ресурс, уд",[7,13],"Deadlock (взаимная блокировка) — ситуация, когда две или более транзакции блокируют друг друга, каждая ожидая ресурс, удерживаемый другой. PostgreSQL автоматически обнаруживает deadlock и откатывает одну из транзакций.",true]