如何防止 psycopg2 锁定 table

How to prevent psycopg2 locking a table

我在 PostgreSQL 9.1 服务器上有一个 table,如下所示:

CREATE TABLE foo(id integer PRIMARY KEY);

在与 psycopg2 (≥ 2.4.2) 的交互 Python shell 中,我可能会启动连接和游标,并查询此 table:

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

但是,如果我随后尝试修改 table:

ALTER TABLE foo ADD COLUMN bar integer;

这开始了一个虚拟死锁,直到我从 Python 执行 conn.close()

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

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

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

autocommit 的文档警告:

By default, any query execution, including a simple SELECT will start a transaction: for long-running programs, if no further action is taken, the session will remain “idle in transaction”, an undesirable condition for several reasons (locks are held by the session, tables bloat...). For long lived scripts, either ensure to terminate a transaction as soon as possible or use an autocommit connection.

这题用简单的SELECT总结了经验

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

Transactions are handled by the connection class. By default, the first time a command is sent to the database (using one of the cursors created by the connection), a new transaction is created. The following database commands will be executed in the context of the same transaction – not only the commands issued by the first cursor, but the ones issued by all the cursors created by the same connection. Should any command fail, the transaction will be aborted and no further command will be executed until a call to the rollback() method.

基本上 psycopg2 为所有 t运行 使用同一连接的操作锁定 table。