2

我正在编写一个脚本来访问已建立数据库中的数据,不幸的是,我正在破坏数据库。我可以从命令行重新创建问题:

    [user@box tmp]# python
    Python 2.7.2(默认,2011 年 9 月 19 日,15:02:41)
    [GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] 在 linux2 上
    输入“帮助”、“版权”、“信用”或“许可”以获取更多信息。
    >>> 导入 pgdb
    >>> db = pgdb.connect('localhost:my_db:postgres')
    >>> cur = db.cursor()
    >>> cur.execute("SELECT * FROM mytable LIMIT 10")
    >>> cur.close()
    >>>

此时,对 mytable 的任何活动都会大大降低,“select * from pg_stat_activity”将我的连接显示为“IDLE in transaction”。如果我调用 db.close() 一切都很好,但我的脚本无限循环,我认为我不需要打开和关闭每个循环的数据库连接。我认为这与我没有使用上面的数据这一事实没有任何关系,因为在我的真实脚本中我正在调用 fetchone() (在循环中)来处理数据。我不是数据库专家,所以我不确定还有什么其他信息有用。如上所示,我的 postgres 版本是 9.1.0,python 是 2.7.2。

4

2 回答 2

2

在关闭光标之前尝试调用db.rollback()(或者如果您正在执行写操作,请尝试调用db.commit())。

于 2011-10-06T01:22:58.827 回答
2

我建议使用 psycopg2 而不是 pgdb。pgdb 使用以下语义:

connect() -> 打开数据库连接,开始事务
commit() -> 提交,开始事务
回滚() -> 回滚,开始事务
执行() -> 执行语句

另一方面,psycopg2 使用以下语义:

connect() -> 打开数据库连接
commit() -> commit
rollback() -> rollback
execute() -> 开始事务,除非已经在事务中,否则执行语句

因此,正如 Amber 所提到的,您可以在 select 语句之后执行回滚或提交并终止事务。不幸的是,使用 pgdb,您将在回滚或提交后立即启动一个新事务(即使您没有执行任何工作)。

对于许多数据库系统,pgdb 的行为很好,但是由于 PostgreSQL 处理事务的方式,如果您有很多连接访问相同的表,它可能会给您带来麻烦(特别是与真空有关的麻烦)。

为什么 pgdb 会立即开始事务?Python DB-API (2.0) 规范要求它这样做。对我来说似乎有点傻,但这就是规范的编写方式。

于 2011-10-06T04:34:31.477 回答