【问题标题】:How do I do database transactions with psycopg2/python db api?如何使用 psycopg2/python db api 进行数据库事务?
【发布时间】:2010-11-16 04:49:30
【问题描述】:

我在摆弄 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 一起工作? 我将如何设置/更改隔离级别?

【问题讨论】:

    标签: python database postgresql


    【解决方案1】:

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

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

    正如here 记录的那样,psycopg2.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
    

    【讨论】:

    • 不错。它是否默认为自动提交?当设置 n=1,2 或 3 时,什么开始交易?创建一个新游标,或者只是自上次提交/回滚以来对数据库的每个操作?
    • 自动提交是大多数 DBMS 的默认设置。
    • Alex 在我询问后添加了更多内容。它说 READ_COMMITED 是 psycopg2 的默认值
    • 启动事务的是前一个事务的提交或回滚。
    【解决方案2】:

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

    您可以按照 Alex Martelli 的指示,使用 db.set_isolation_level(n) 将隔离级别更改为自动提交。

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

    【讨论】:

    • 这是真的吗?我相信在调用 commit() 或 rollback() 之后,not 会立即发送另一个 BEGIN——它是在下一个 execute() 中隐式发送的。在提交()/回滚()之后,连接处于“空闲”状态而不是“事务中空闲”。
    • 在 commit()/rollback() 之后,连接处于“空闲”状态。 Python DB API 将仅在另一个 execute() 之后发送另一个 BEGIN,因此如果您的程序永远不会结束,您就不会造成死锁。总结一下,一旦你调用了 execute(),你应该 commit() 或 rollback(),否则你的程序将“在事务中空闲”。
    【解决方案3】:

    我更喜欢明确地查看我的交易在哪里:

    • cursor.execute("BEGIN")
    • cursor.execute("COMMIT")

    【讨论】:

    • 自动提交是打开还是关闭?它会混淆 Psycopg2 或其他数据库模块吗? ODBC 的事务管理使用与 python DB API 类似的方法,我已经看到明确的警告not使用破坏 ODBC 接口的 SQL 事务管理命令(例如msdn.microsoft.com/en-us/library/ms131281.aspx)。
    • 请不要那样做。您将与自动提交功能作斗争,不能保证结果会很好。
    • 自动提交关闭。
    • 自动提交功能也让我害怕,所以我想知道我们是否应该将其关闭并以这种方式进行。如果可以的话,我愿意。
    • 使用自动提交的原因是,如果您使用像 pgbouncer 这样的外部池,则连接会保存到提交,这意味着如果您没有在您的 Web 服务器上正确管理事务(并实际上完全关闭游标)将有剩余的“空闲事务”连接。启用自动提交后,游标不会自动占用服务器资源,但您仍然可以通过将 tcp 套接字设置到池中来节省时间。
    猜你喜欢
    • 1970-01-01
    • 2010-11-30
    • 2010-09-23
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    相关资源
    最近更新 更多