在自动提交模式下运行BEGIN时Postgres做了什么?
我想更好地理解在使用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 个回答
当自动提交功能开启时,psycopg会直接把所有操作发送到PostgreSQL数据库,而不帮你管理事务。如果你不使用BEGIN/COMMIT/ROLLBACK这些命令,那么每次调用.execute()时,操作都会立刻执行并提交。你可以通过发出BEGIN/COMMIT/ROLLBACK命令来自己管理事务。显然,在自动提交模式下,你不能调用conn.commit()或conn.rollback(),因为psycopg并没有跟踪事务,只是把你执行的操作直接发送到数据库。
在你的例子中,A和B会被提交,而C和D会被撤销。
默认情况下,PostgreSQL是开启自动提交的,这意味着每条语句都会被当作一个事务来处理。如果你明确告诉它开始一个事务,就像你在例子中那样,那么这些操作就会在一个新的事务中进行。
在你的例子中,A和B会被提交,而C和D则会被撤销。
自动提交模式意味着每条语句都会自动开始和结束一个事务。
在你的情况下,如果自动提交是关闭的:
- 客户端会自动为第一条语句开始一个事务
- 当你使用
BEGIN
时,会发出一个警告,提示事务已经开始了 - 使用
ROLLBACK
时,会撤销所有四条语句的操作
当自动提交开启时,只有 c
和 d
这两条语句会被撤销。
需要注意的是,自从 8.0
版本以来,PostgreSQL
并没有内部的 AUTOCOMMIT
行为,所有的自动提交功能都是依赖于客户端来处理的。