在自动提交模式下运行BEGIN时Postgres做了什么?

1 投票
3 回答
1636 浏览
提问于 2025-04-15 20:36

我想更好地理解在使用Postgres(psycopg)连接时的“自动提交”这个概念。假设我有一个新的连接,把它的隔离级别设置为ISOLATION_LEVEL_AUTOCOMMIT,然后直接运行这个SQL,不使用游标的开始/回滚方法(只是练习,不是说我真的想这么做):

INSERT A
INSERT B
BEGIN
    INSERT C
    INSERT D
ROLLBACK

那么,INSERT语句C和D会发生什么呢?

自动提交只是psycopg内部的一个设置,它影响的是如何发出BEGIN命令吗?如果是这样,上面的SQL就不受影响;INSERT语句A和B在完成后会立即提交,而C和D则是在一个事务中执行并被回滚。那么,这个事务是在哪个隔离级别下运行的呢?

还是说自动提交是连接本身的一个真实设置?如果是这样,它是如何影响BEGIN命令的处理的?是被忽略,还是会覆盖自动提交的设置,真正开始一个事务?这个事务又是在哪个隔离级别下运行的呢?

还是说我完全理解错了?

3 个回答

1

当自动提交功能开启时,psycopg会直接把所有操作发送到PostgreSQL数据库,而不帮你管理事务。如果你不使用BEGIN/COMMIT/ROLLBACK这些命令,那么每次调用.execute()时,操作都会立刻执行并提交。你可以通过发出BEGIN/COMMIT/ROLLBACK命令来自己管理事务。显然,在自动提交模式下,你不能调用conn.commit()或conn.rollback(),因为psycopg并没有跟踪事务,只是把你执行的操作直接发送到数据库。

在你的例子中,A和B会被提交,而C和D会被撤销。

1

默认情况下,PostgreSQL是开启自动提交的,这意味着每条语句都会被当作一个事务来处理。如果你明确告诉它开始一个事务,就像你在例子中那样,那么这些操作就会在一个新的事务中进行。

在你的例子中,A和B会被提交,而C和D则会被撤销。

3

自动提交模式意味着每条语句都会自动开始和结束一个事务。

在你的情况下,如果自动提交是关闭的:

  • 客户端会自动为第一条语句开始一个事务
  • 当你使用 BEGIN 时,会发出一个警告,提示事务已经开始了
  • 使用 ROLLBACK 时,会撤销所有四条语句的操作

当自动提交开启时,只有 cd 这两条语句会被撤销。

需要注意的是,自从 8.0 版本以来,PostgreSQL 并没有内部的 AUTOCOMMIT 行为,所有的自动提交功能都是依赖于客户端来处理的。

撰写回答