Механизм блокировки в postgres/ Взаимоблокировки в postgres. [Я использую sqlalchemy]

Я совершенно не понимаю, как работает механизм блокировки в sqlalchemy-psql. Я запускаю приложение python-flask с sqlalchemy и postgres. Поскольку у меня есть несколько потоков, обрабатывающих некоторые данные и обновляющих их в psql, я получаю следующий тупик:

2015-12-31 17: [ОШИБКА] (возникла в результате автосброса, вызванного запросом; рассмотрите возможность использования блока session.no_autoflush, если этот сброс происходит преждевременно) (psycopg2.extensions.TransactionRollbackError) обнаружена взаимоблокировка

ПОДРОБНО: Процесс 22833 ожидает ShareLock для транзакции 14114188; заблокирован процессом 19759.

Процесс 19759 ожидает ShareLock для транзакции 14114189; заблокирован процессом 22833.

Вот как может возникнуть взаимоблокировка:

Thread 1                                       Thread 2                                   
| (start an sqlalchemy session)                |
 db.session()                                  db.session()
|(Using sqlalchemy)                            |
Update row1 of table1                          Update row2 of table 1
|                                              |
Update row2 of table1                          Update row1 of table1
|                                              |  
session.commit()                               session.commit()

Вот несколько ответов на мою проблему, но я не могу связать их с sqlalchemy.


person DarthSpeedious    schedule 05.01.2016    source источник


Ответы (1)


В PostgreSQL строки будут блокироваться по мере их обновления — на самом деле это работает так, что каждый кортеж (версия строки) имеет системное поле с именем xmin, указывающее, какая транзакция сделала этот кортеж текущим (посредством вставки или обновления). ) и системное поле с именем xmax, чтобы указать, какая транзакция устарела для этого кортежа (путем обновления или удаления). Когда вы получаете доступ к данным, он проверяет каждый кортеж, чтобы определить, виден ли он для вашей транзакции, сверяя ваш активный «моментальный снимок» с этими значениями.

Если вы выполняете UPDATE и кортеж, который соответствует вашим условиям поиска, имеет xmin, который сделает его видимым для вашего снимка, и xmax активной транзакции, он блокируется, ожидая завершения этой транзакции. Если транзакция, которая первой обновила кортеж, откатывается, ваша транзакция просыпается и обрабатывает строку; если первая транзакция фиксируется, ваша транзакция просыпается и выполняет действие в зависимости от текущего уровня изоляции транзакции.

Очевидно, взаимоблокировка является результатом того, что это происходит со строками в другом порядке. В ОЗУ нет блокировки на уровне строк, которую можно получить для всех строк одновременно, но если строки обновляются в одном и том же порядке, у вас не может быть циклической блокировки. К сожалению, предлагаемый синтаксис IN(1, 2) не гарантирует этого. В разных сеансах могут быть активны разные факторы стоимости, фоновая задача «анализа» может изменить статистику для таблицы между генерацией одного плана и другого, или она может использовать seqscan и быть затронутой оптимизацией PostgreSQL, которая вызывает новое seqscan чтобы присоединиться к уже выполняющемуся и «зациклиться», чтобы уменьшить дисковый ввод-вывод.

прочитайте это http://elioxman.blogspot.in/2013/02/postgres-deadlock.html

person Anurag jain    schedule 09.01.2016