【问题标题】:Does dropping a database have to be done not in any transaction?删除数据库是否必须在任何事务中完成?
【发布时间】:2026-02-11 01:20:02
【问题描述】:

来自https://wiki.postgresql.org/wiki/Psycopg2_Tutorial

PostgreSQL 不能在事务中删除数据库,它是一个全部 或没有命令。如果要删除数据库,则需要 更改数据库的隔离级别,这是使用 关注。

conn.set_isolation_level(0)

您可以将上述内容放在 DROP DATABASE 之前 游标执行。

为什么“如果要删除数据库,则需要更改数据库的隔离级别”? 特别是,为什么我们需要将隔离级别更改为 0? (如果我是正确的,0 表示psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED

来自https://*.com/a/51859484/156458

销毁数据库的操作是这样实现的 防止撤消它 - 因此 您不能从内部运行它 事务,因为事务总是可撤消的。 还要保持 请注意,与大多数其他数据库不同,PostgreSQL 允许几乎所有 DDL 要在内部执行的语句(显然不是 DROP DATABASE 之一) 一笔交易。

实际上,如果任何人(包括您)是 当前连接到这个数据库 - 所以不管是什么 您的隔离级别,您仍然需要连接到另一个数据库 (例如 postgres)

“您不能从事务内部运行它,因为事务总是可撤消的”。那我怎样才能不从事务内部删除数据库呢?


我在https://*.com/a/51880577/156458找到了答案

【问题讨论】:

  • 使用 PHP 你可以像$db = new PDO('some other database, e.g. postgres'); $db->query('DROP DATABASE your_original_database');这样销毁数据库。我不知道如何在 Python 中做到这一点。
  • 连接到不同的数据库。不要打开交易。删除你想要的数据库。
  • @KamilG。每个SQL命令默认都是一个事务,如何让一个命令不在任何事务中?
  • 我敢打赌,您只需在查询执行之前和数据库更改之后执行self.conn.set_isolation_level(0)。然后,切换回旧的隔离级别。确保事先将其存储在变量中。
  • @KamilG。您的意思是在删除数据库之前和之后两次?

标签: postgresql psycopg2


【解决方案1】:

我对 psycopg2 不熟悉,所以我只能提供要执行的步骤。

Python执行DROP DATABASE的步骤:

  1. 连接到您不想删除的其他数据库
  2. 将当前隔离级别存储在变量中
  3. 将隔离级别设置为 0
  4. 执行DROP DATABASE查询
  5. 将隔离级别设置回原始级别(来自 #2)

PSQL执行DROP DATABASE的步骤:

  1. 连接到您不想删除的其他数据库
  2. 执行DROP DATABASE查询

psql 中的代码

\c second_db
DROP DATABASE first_db;

请记住,您尝试删除的数据库可能没有实时连接。

【讨论】:

  • 谢谢。 (1) 在 PostgreSQL 中,每个 SQL 命令默认是一个事务。根据我帖子中的报价,我们必须不在任何事务中删除数据库。可以更改为 Postgres db 的隔离级别 READ_COMMITTED 使删除数据库不在任何事务中吗? (2) 为什么 psycopg2 需要显式更改和恢复隔离级别,而 psql 需要显式更改和恢复隔离级别,因为 postgresql 服务器的默认隔离级别是 READ_COMMIT?
  • (1) 您不必担心 PostgreSQL 中的隐式事务。我们谈论的是显式的,所以你不能用BEGIN 开始一个事务。 (2) 我相信将隔离级别设置为0 实际上意味着一个常量值ISOLATION_LEVEL_AUTOCOMMIT 但你必须检查一下。这意味着我们将关闭显式事务打开。无需更改 Postgres 中的实际隔离级别,因为我想这并不重要。
  • 谢谢。我对自动提交在 postgresql 和 psycopg2 *.com/questions/51880309/… 中的含义感到困惑