postgres - 无法使用psycopg2删除数据库

11 投票
1 回答
10344 浏览
提问于 2025-04-17 21:58

我正在尝试用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代码启动了两个进程!一个是我明确连接到Postgres数据库的,另一个是连接到我想删除的数据库(crowdsurfer)。注意它是空闲状态,它运行的查询是SET default_transaction_isolation TO 'read committed'。

所以看起来将conn.autocommit设置为true会创建一个新进程???对此你有什么想法,怎么才能删除这个数据库呢?

1 个回答

4

事情是这样的。导入的一个类里有个装饰器,它负责打开连接。这个装饰器是Django里常用的transaction.atomic(我其实是错误地把它应用到了一个类上,而不是方法上)。显然,它是在导入的过程中执行的,这就打开了与Postgres数据库的连接。

撰写回答