python pgdb 数据库挂起

2 投票
2 回答
1579 浏览
提问于 2025-04-17 03:45

我正在写一个脚本,用来访问一个已经建立好的数据库,但不幸的是,我把数据库搞坏了。我可以通过命令行重现这个问题:

    [user@box tmp]# python
    Python 2.7.2 (default, Sep 19 2011, 15:02:41) 
    [GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import 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,如上所示。

2 个回答

2

我建议使用psycopg2,而不是pgdb。pgdb的操作方式是这样的:

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

而psycopg2的操作方式则是:

connect() -> 打开数据库连接
commit() -> 提交
rollback() -> 回滚
execute() -> 如果还没有在事务中,就开始一个事务,然后执行语句

所以,正如Amber提到的,你可以在执行选择语句后进行回滚或提交,然后结束事务。不幸的是,使用pgdb时,一旦你回滚或提交,就会立即开始一个新的事务(即使你没有做任何操作)。

对于很多数据库系统来说,pgdb的这种行为是可以接受的,但由于PostgreSQL处理事务的方式,如果有很多连接同时访问同一张表,这可能会给你带来麻烦(特别是在进行清理操作时)。

为什么pgdb会立即开始一个事务呢?因为Python的数据库API(2.0)规范要求这样做。我觉得这有点傻,但这就是规范的写法。

2

在你关闭光标之前,试着先调用一下 db.rollback(),或者如果你正在进行写入操作的话,就用 db.commit()

撰写回答