我正在编写一个脚本来访问已建立的数据库中的数据,不幸的是,我正在破坏数据库。我可以从命令行重新创建问题:
[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”。如果我调用db.close()一切都很好,但我的脚本无限循环,我不认为我需要打开和关闭每个循环的数据库连接。我不认为它与我不使用上面的数据这一事实有关,因为在我的真实脚本中我调用fetchone()(在循环中)来处理数据。我不是一个数据库人,所以我不确定其他信息会有用。我的postgres版本是9.1.0,python是2.7.2,如上所示。
答案 0 :(得分:1)
在关闭光标之前尝试调用db.rollback()
(或者如果您正在执行写操作db.commit()
)。
答案 1 :(得分:1)
我建议使用psycopg2而不是pgdb。 pgdb使用以下语义:
connect() - >打开数据库连接,开始交易
commit() - >提交,开始交易
rollback() - >回滚,开始交易
execute() - >执行声明
psycopg2使用以下语义:
connect() - >打开数据库连接
commit() - >提交
rollback() - >回滚
execute() - >除非已在事务中,否则开始事务,执行语句
因此,正如Amber所提到的,您可以在select语句之后执行回滚或提交并终止事务。不幸的是,使用pgdb,您将在回滚或提交后立即启动一个新事务(即使您没有执行任何工作)。
对于许多数据库系统,pgdb的行为很好,但由于PostgreSQL处理事务的方式,如果你有很多连接访问相同的表(特别是真空故障),它会给你带来麻烦。
为什么pgdb会马上开始交易? Python DB-API(2.0)规范要求它这样做。对我来说似乎有些愚蠢,但这就是编写规范的方式。