如何使用psycopg2/python db api进行数据库事务处理?

2024-04-25 18:56:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我在摆弄psycopg2,虽然有一个.commit()和.rollback(),但没有.begin()或类似的方法来启动事务,或者看起来是这样? 我希望能做到

db.begin() # possible even set the isolation level here
curs = db.cursor()
cursor.execute('select etc... for update')
...
cursor.execute('update ... etc.')
db.commit();

那么,事务如何与psycopg2一起工作呢? 如何设置/更改隔离级别?


Tags: the方法executedbetcupdate事务cursor
3条回答

使用db.set_isolation_level(n),假设db是连接对象。正如Federico写的heren的意思是:

0 -> autocommit
1 -> read committed
2 -> serialized (but not officially supported by pg)
3 -> serialized

正如所记录的herepsycopg2.extensions为您提供符号常量:

Setting transaction isolation levels
====================================

psycopg2 connection objects hold informations about the PostgreSQL `transaction
isolation level`_.  The current transaction level can be read from the
`.isolation_level` attribute.  The default isolation level is ``READ
COMMITTED``.  A different isolation level con be set through the
`.set_isolation_level()` method.  The level can be set to one of the following
constants, defined in `psycopg2.extensions`:

`ISOLATION_LEVEL_AUTOCOMMIT`
    No transaction is started when command are issued and no
    `.commit()`/`.rollback()` is required.  Some PostgreSQL command such as
    ``CREATE DATABASE`` can't run into a transaction: to run such command use
    `.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)`.

`ISOLATION_LEVEL_READ_COMMITTED`
    This is the default value.  A new transaction is started at the first
    `.execute()` command on a cursor and at each new `.execute()` after a
    `.commit()` or a `.rollback()`.  The transaction runs in the PostgreSQL
    ``READ COMMITTED`` isolation level.

`ISOLATION_LEVEL_SERIALIZABLE`
    Transactions are run at a ``SERIALIZABLE`` isolation level.


.. _transaction isolation level: 
   http://www.postgresql.org/docs/8.1/static/transaction-iso.html

python标准DB API的BEGIN总是隐式的。当您开始使用数据库时,驱动程序会发出一个BEGIN,并且在发出任何COMMITROLLBACK之后,会发出另一个BEGIN。符合规范的python DB API应该总是这样工作的(不仅仅是postgresql)。

如Alex Martelli所指出,您可以使用db.set_isolation_level(n)将隔离级别更改为autocommit。

正如Tebas所说,begin是隐式的,但在执行SQL之前不会执行,因此如果不执行任何SQL,则会话不在事务中。

我更愿意明确地看到我的交易在哪里:

  • cursor.execute(“开始”)
  • cursor.execute(“提交”)

相关问题 更多 >