使用psycopg2或"with closing"结合try/except使用。
使用psycopg2或"with closing"结合try/except使用。
我在Python中使用Psycopg2访问PostgreSQL数据库。我想知道是否可以安全地使用with closing()
模式来创建和使用游标,还是应该在查询周围使用显式的try/except
语句。我的问题涉及插入、更新和事务。
据我了解,所有Psycopg2查询都在一个事务中进行,由调用代码来提交或回滚事务。如果在with closing(...
块内发生错误,会发出回滚吗?在旧版本的Psycopg2中,close()
会显式发出回滚,但现在不再是这样了(参见http://initd.org/psycopg/docs/connection.html#connection.close)。
通过一个例子,我的问题可能更容易理解。这是一个使用with closing(...
的例子:
with closing(db.cursor()) as cursor: cursor.execute("""UPDATE users SET password = %s, salt = %s WHERE user_id = %s""", (pw_tuple[0], pw_tuple[1], user_id)) module.rase_unexpected_error() cursor.commit()
当module.raise_unexpected_error()引发错误时会发生什么?事务会回滚吗?据我了解,事务要么需要提交,要么需要回滚。那么在这种情况下会发生什么?
或者我可以像这样编写我的查询:
cursor = None try: cursor = db.cursor() cursor.execute("""UPDATE users SET password = %s, salt = %s WHERE user_id = %s""", (pw_tuple[0], pw_tuple[1], user_id)) module.rase_unexpected_error() cursor.commit() except BaseException: if cursor is not None: cursor.rollback() finally: if cursor is not None: cursor.close()
还要提一下,我不知道Psycopg2的连接类cursor()
方法是否会引发错误(文档没有提到),所以最好还是保险起见,对吧?
我应该使用哪种方法来执行查询和管理事务?
问题的原因:当使用"with closing()"(psycopg2 2.4.5)时,如果出现SQL异常,事务仍然处于进行中。在此之后,如果尝试在数据库连接上执行其他操作,将导致引发"InternalError: current transaction is aborted"错误。
解决方法:可以使用try/except方法进行更细粒度的事务控制,因为它与数据库事务状态本身相对应。如果出现异常,可以在try块中进行回滚操作,确保事务的完整性。以下是一个示例代码:
import psycopg2 try: # 连接数据库 conn = psycopg2.connect(database="your_database", user="your_user", password="your_password", host="your_host", port="your_port") # 开始事务 conn.autocommit = False cursor = conn.cursor() try: # 执行SQL语句 cursor.execute("INSERT INTO your_table (column1, column2) VALUES (value1, value2)") # 提交事务 conn.commit() except Exception as e: # 出现异常时回滚事务 conn.rollback() print("Error:", e) finally: # 关闭游标和连接 cursor.close() conn.close() except Exception as e: print("Unable to connect to the database:", e)
通过使用try/except方法,我们可以在出现异常时回滚事务,确保数据的一致性。同时,我们还可以在finally块中关闭游标和连接,以释放资源。
需要注意的是,try/except方法只适用于单个连接。如果需要在多个连接之间执行事务操作,可以考虑使用连接池来管理连接。