【问题标题】:postgres - cannot drop database using psycopg2postgres - 无法使用 psycopg2 删除数据库
【发布时间】:2014-03-12 16:27:46
【问题描述】:

所以我只是尝试使用 Python 的 psycopg2 删除并重新创建我的数据库。这是我的代码:

    with psycopg2.connect(database="postgres", user="postgres", password="****") as conn:
    with conn.cursor() as cur:
        conn.autocommit = True   #  Explains why we do this - we cannot drop or create from within a DB transaction. http://initd.org/psycopg/docs/connection.html#connection.autocommit
        cur.execute("DROP DATABASE crowdsurfer;")
        cur.execute("CREATE DATABASE crowdsurfer;")

当我运行这段代码时,我得到了

PS C:\Users\Nick\Documents\GitHub\CrowdSurfer\CrowdSurfer> python utils/sqlInit.py
Traceback (most recent call last):

  File "utils/sqlInit.py", line 70, in <module>
    run()

  File "utils/sqlInit.py", line 21, in run
recreate_empty_database()

  File "utils/sqlInit.py", line 40, in recreate_empty_database
    cur.execute("DROP DATABASE crowdsurfer;")

psycopg2.OperationalError: database "crowdsurfer" is being accessed by other users
DETAIL:  There is 1 other session using the database.

好吧,够公平的。所以我打开了一个到 postgres 的连接,并在我的代码运行之前和期间查看了现有的处理。在我的代码开始之前,我们得到了这个:

postgres=# select pid from pg_stat_activity

此命令返回单个 PID,PID 6052

这个过程是我的,所以很好。现在这是我在运行 python 代码时查询运行进程时得到的结果:

 postgres=# select * from pg_stat_activity;
 datid  |   datname   | pid  | usesysid | usename  | application_name | client_addr | client_hostname | client_port |       backend_start        |         xact_start         |        query_start         |
       state_change        | waiting | state  |                         query

  12029 | postgres    | 6052 |       10 | postgres | psql             | ::1         |                 |       49842 | 2014-03-11 23:14:34.049-06 | 2014-03-11 23:14:58.938-06 | 2014-03-11 23:14:58.938-06 |

2014-03-11 23:14:58.938-06 | f       | active | select * from pg_stat_activity;
 142547 | crowdsurfer | 3952 |       10 | postgres |                  | 127.0.0.1   |                 |       49849 | 2014-03-11 23:14:57.489-06 |                            | 2014-03-11 23:14:57.491-06 |
2014-03-11 23:14:57.491-06 | f       | idle   | SET default_transaction_isolation TO 'read committed'

  12029 | postgres    | 7908 |       10 | postgres |                  | ::1         |                 |       49851 | 2014-03-11 23:14:57.556-06 | 2014-03-11 23:14:57.559-06 | 2014-03-11 23:14:57.559-06 |
2014-03-11 23:14:57.559-06 | f       | active | DROP DATABASE crowdsurfer;
(3 rows)

python代码启动了2个进程!一个连接到我明确执行的 postgres 数据库。另一个连接到我要删除的数据库(crowdsurfer)。注意它是空闲的,它运行的查询是 SET default_transaction_isolation TO 'read committed'

所以似乎将 conn.autocommit 设置为 true 是在创建一个新进程???有什么想法可以在这里删除这个数据库吗?

【问题讨论】:

  • psycopg2 不会打开任何额外的连接,而是为每个connect() 调用创建一个连接。确保您没有从代码的其他部分或使用psql 的命令行访问crowdsurfer
  • 你是对的。我设置了几个断点,然后查看了活动进程。当我在 if name == "main": (脚本中的第一行代码)之后立即设置断点时,已经创建了第二个进程。这是否意味着导入正在创建这个 sql 进程?
  • 是的,刚刚验证了正在发生的事情......现在我需要了解如何
  • 想通了:其中一个导入的模块具有一个带有装饰器的功能,该装饰器正在打开连接。我从来不知道装饰器是在导入期间执行的。感谢您的帮助!
  • 我来这里是为了寻找psycopg2.InternalError: DROP DATABASE cannot run inside a transaction block 的解决方案。 conn.autocommit = True 解决了我的问题。谢谢!

标签: python database django postgresql psycopg2


【解决方案1】:

这就是发生的事情。其中一个导入的类有一个正在打开连接的装饰器。这是一个标准的 Django 装饰器 transaction.atomic(我实际上错误地将它应用于一个类而不是一个方法)。显然它是在导入过程中执行的,打开了与 postgres 数据库的连接。

【讨论】:

    猜你喜欢
    • 2019-12-14
    • 2016-07-31
    • 2019-06-02
    • 2023-03-03
    • 1970-01-01
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    相关资源
    最近更新 更多