【问题标题】:How to prevent psycopg2 locking a table如何防止 psycopg2 锁定表
【发布时间】:2016-08-14 02:31:01
【问题描述】:

我在 PostgreSQL 9.1 服务器上有一张这样的表:

CREATE TABLE foo(id integer PRIMARY KEY);

在一个带有 psycopg2 (≥ 2.4.2) 的交互式 Python shell 中,我可能会启动一个连接和游标,然后查询这个表:

import psycopg2
conn = psycopg2.connect('dbname=...')
curs = conn.cursor()
curs.execute('SELECT * FROM foo;')
curs.fetchall()

但是,如果我尝试修改表格:

ALTER TABLE foo ADD COLUMN bar integer;

这会导致虚拟死锁,直到我从 Python 执行 conn.close()。

如何启动与 psycopg2 的简单连接,以防止它在其他地方创建由 DDL 更改引起的死锁? Python 中的连接可以是只读的。

【问题讨论】:

    标签: python postgresql postgresql-9.1 psycopg2 database-deadlocks


    【解决方案1】:

    我找到的解决方案是像这样使用set_session:

    conn.set_session(readonly=True, autocommit=True)
    

    autocommit 的文档警告:

    默认情况下,任何查询执行,包括一个简单的 SELECT 都会启动一个事务:对于长时间运行的程序,如果不采取进一步的行动,会话将保持“在事务中空闲”,这是出于多种原因(锁由会议举行,表格膨胀......)。对于长期存在的脚本,请确保尽快终止事务或使用自动提交连接。

    这总结了问题中一个简单的SELECT的经验。

    【讨论】:

    • 您也可以只输入conn.commit() 而不是将autocommit 设置为True
    【解决方案2】:

    仅供参考,我在使用 psycopg2 进行并发写入时遇到了同样的问题。文档指出:

    事务由连接类处理。默认情况下, 第一次将命令发送到数据库(使用其中一个游标 由连接创建),一个新的事务被创建。这 以下数据库命令将在 相同的事务——不仅是第一个游标发出的命令, 但是由同一连接创建的所有游标发出的游标。 如果任何命令失败,事务将被中止并且没有 将执行进一步的命令,直到调用 rollback() 方法。

    基本上 psycopg2 为使用同一连接的所有事务锁定表。

    【讨论】:

    • 除了上面的答案之外,您还可以通过在 SQL 语句前加上“BEGIN;”来防止表锁定。以及用“END;”结束它。这真的取决于你想要做的事情的范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    相关资源
    最近更新 更多