Проводятся ли транзакции в PostgreSQL через `psycopg2` для каждого курсора или для каждого соединения?

10

Я делаю некоторую работу с PostgreSQL 9.3, используя psycopg2API базы данных.

У меня API БД установлен на минимальном уровне изоляции (режим «автокоммит»), и я управляю своими собственными транзакциями напрямую через SQL. Пример:

cur = self.conn.cursor()
cur.execute("BEGIN;")
cur.execute("SELECT dbId, downloadPath, fileName, tags FROM {tableName} WHERE dlState=%s".format(tableName=self.tableName), (2, ))
ret = cur.fetchall()
cur.execute("COMMIT;")

По сути, транзакция, которая запускается cur.execute("BEGIN;")ограниченным только этим курсором, или это для всего соединения ( self.conn.cursor())?

Некоторые из более сложных вещей, которые я делаю, включают несколько отдельных операций с базой данных, которые я логически разбиваю на функции. Поскольку это все в классе, который имеет соединение в качестве члена, гораздо удобнее создавать курсоры внутри каждой функции. Однако я не уверен, как работает создание курсоров в транзакции.

По сути, если транзакции относятся к каждому соединению, я могу просто создавать множество курсоров внутри транзакции. Если они для каждого курсора, это означает, что я должен перемещать курсор повсюду. Что он?

Документация не касается этого, хотя тот факт , что вы можете назвать connection.commit()делает меня довольно уверен , что сделка, контроль за соединение.

Поддельное имя
источник

Ответы:

7

Транзакции происходят за сеанс, то есть за соединение.

PostgreSQL не поддерживает приостановку и возобновление транзакций, поэтому psycopg2 не может делать их для каждого курсора, если он неявно создает новые соединения за кулисами.

На практике я не нахожу курсоры psycopg2 особенно полезными. Они могут сохранять наборы результатов, если вы не используете инкрементную выборку с сервера, но я не нахожу их полезными для чего-то еще.

Зачем вручную выдавать beginи commitхотя, а не использовать для них методы подключения?

Крейг Рингер
источник
Как следует из документации, вся модель «DB API» на самом деле вообще не поддерживает явные транзакции.
Фальшивое имя
1
@FakeName Вы не должны явно begin. Если ни одна транзакция не открыта, для вас запускается новая. Вы просто commitразграничить транзакции. Так что да, модель DB-API делает поддержку явные транзакции.
Крейг Рингер,
1
Если DB API делает это автоматически, без моего специального указания на это, это очень неявное начало. И кроме того, это не имеет значения, поскольку (как я уже говорил в вопросе) я использую режим автоматической фиксации, потому что я не хочу этих автоматических BEGINутверждений. Я не хочу psycopg2создавать новую транзакцию для каждой SELECT.
Фальшивое имя
TL; DR в основном я хочу знать точную область действия всех транзакций, потому что A. Я сумасшедший в этом смысле, и B. это очень помогает при отладке.
Фальшивое имя
1
Я не был бы удивлен, увидев странные ошибки, появляющиеся с этим. AFAIK autocommit на самом деле означает autocommit, а не управление транзакциями вручную. Если вы действительно хотите вручную управлять областями транзакций, дополнительные BEGINбезвредны и будут просто игнорироваться PostgreSQL WARNING: there is already a transaction in progress.
Крейг Рингер
1

Из документации psycopg2 :

В Psycopg транзакции обрабатываются классом соединения. По умолчанию при первой отправке команды в базу данных (с использованием одного из курсоров, созданных соединением) создается новая транзакция. Следующие команды базы данных будут выполняться в контексте одной и той же транзакции - не только команды, выданные первым курсором, но и команды, выданные всеми курсорами, созданными одним и тем же соединением. В случае сбоя какой-либо команды транзакция будет прервана, и дальнейшая команда не будет выполнена до вызова метода rollback ().

В то же время, начиная с версии 2.4.2, есть autocommitатрибут (выделение добавлено):

Атрибут Чтение / запись: если Trueдрайвер не обрабатывает транзакции, и каждый оператор, отправляемый бэкэнду, имеет немедленный эффект; если False новая транзакция запускается при первом выполнении команды : методы commit()или rollback()должны быть вызваны вручную для завершения транзакции.

Режим автоматической фиксации полезен для выполнения команд, требующих запуска вне транзакции, таких как CREATE DATABASEили VACUUM.

По умолчанию False(ручная фиксация) согласно спецификации DBAPI.

Стивен
источник