Проблема взаємоблокування у PostgreSQL та SQLAlchemy

Проблема взаємоблокування у PostgreSQL та SQLAlchemy

4 Березня 2024 в 15:03 42

Багаторазово виникає проблема взаємоблокування (deadlock) у веб-додатку, який використовує Python FastAPI, SQLAlchemy як ORM та PostgreSQL як базу даних. Ця проблема є серйозною та може спричинити недоступність системи для користувачів. Давайте розберемося, чому вона виникає та як її вирішити.

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

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

У нашому випадку, у логах ми бачимо наступне повідомлення про помилку:

Це повідомлення показує, що процес з ідентифікатором 1007755 чекає на отримання блокування для релації з ідентифікатором 1232042, тоді як процес з ідентифікатором 1007749 чекає на блокування для об’єкта з ідентифікатором 3007868. Обидва процеси зачекані один на одного, що призводить до взаємного блокування.

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

У нашому випадку, можна переглянути код, який викликає взаємоблокування, та спробувати оптимізувати його. Також можна розглянути можливість використання асинхронного програмування для зменшення часу очікування на блокування.

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

У будь-якому випадку, вирішення проблеми взаємоблокування у PostgreSQL та SQLAlchemy є складною задачею, яка вимагає уважного аналізу коду та належного розуміння принципів роботи бази даних.