What does Postgres do when BEGIN is run on a connection in autocommit mode?
I'm trying to better understand the concept of 'autocommit' when working with a Postgres (psycopg) connection. Let's say I have a fresh connection, set its isolation level to ISOLATION_LEVEL开发者_如何转开发_AUTOCOMMIT, then run this SQL directly, without using the cursor begin/rollback methods (as an exercise; not saying I actually want to do this):
INSERT A
INSERT B
BEGIN
INSERT C
INSERT D
ROLLBACK
What happens to INSERTs C & D?
Is autocommit is purely an internal setting in psycopg that affects how it issues BEGINs? In that case, the above SQL is unafected; INSERTs A & B are committed as soon as they're done, while C & D are run in a transaction and rolled back. What isolation level is that transaction run under?
Or is autocommit a real setting on the connection itself? In that case, how does it affect the handling of BEGIN? Is it ignored, or does it override the autocommit setting to actually start a transaction? What isolation level is that transaction run under?
Or am I completely off-target?
Autocommit mode means that each statement implicitly begins and ends the transaction.
In your case, if autocommit is off:
- The client will implicitly start the transaction for the first statement
- The
BEGIN
will issue a warning saying that the transaction is already started - The
ROLLBACK
will roll back all four statements
When autocommit is on, only the c
and d
are rolled back.
Note that PostgreSQL
has no internal AUTOCOMMIT
behavior since 8.0
: all autocommit features are relied upon the clients.
By default, PostgreSQL has autocommit on, meaning that each statement is handled as a transaction. If you explicitly tell it to start a transaction, as in your example, those items are in a new transaction.
In your example, A and B would be committed, C and D would be rolled back.
When autocommit is on psycopg just sends everything to the PostgreSQL backend without trying to manage the transaction for you. If you don't use BEGIN/COMMIT/ROLLBACK then every .execute() call is immediately executed and committed. You can do your own transaction management by issuing BEGIN/COMMIT/ROLLBACK commands. Obviously in autocommit mode you can't call conn.commit() or conn.rollback() because psycopg is not keeping track of the transactions but just sending anything you .execute() straight to the backend.
In your example A and B would be committed, C and D would be rolled back.
精彩评论