Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make SQLAlchemy COMMIT instead of ROLLBACK after a SELECT query

I am developing an app together with a partner. I do the database part (PostgreSQL), my partner implements the app on the web-server with python using SQLAlchemy. We make heavy use of stored procedures. A SELECT query on one of those looks like this in the db log:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

SELECT col_a, col_b FROM f_stored_proc(E'myvalue');

ROLLBACK;

In the stored procedures I write certain input to a log table. The app queries by SELECT, SQLAlchemy only sees a SELECT statement and insists on a ROLLBACK. Logging fails. I need it to COMMIT instead. My partner claims there is no easy way, we would have to remove SQLAlchemy altogether. I think he must be wrong but lack the konwledge to claim otherwise.

Is there an easy way to make SQLAlchemy COMMIT instead of ROLLBACK?
What keeps me from just executing trans.commit()? Do I need to set autoflush=False for that?

I have scanned the FAQ, but did not find an answer there.
Searching SO revealed some related questions like here and here, but I am not in the clear.
Maybe this recipe would work?

like image 621
Erwin Brandstetter Avatar asked Sep 26 '11 18:09

Erwin Brandstetter


People also ask

What is lazy dynamic SQLAlchemy?

lazy = 'dynamic': When querying with lazy = 'dynamic', however, a separate query gets generated for the related object. If you use the same query as 'select', it will return: You can see that it returns a sqlalchemy object instead of the city objects.

What does flush do SQLAlchemy?

flush() communicates a series of operations to the database (insert, update, delete). The database maintains them as pending operations in a transaction.

What does all () do in SQLAlchemy?

all() method. The Query object, when asked to return full entities, will deduplicate entries based on primary key, meaning if the same primary key value would appear in the results more than once, only one object of that primary key would be present.

How do I create a transaction in SQLAlchemy?

Whenever you query the database, a transaction automatically starts (SQLAlchemy doesn't do anything special to make this happen, it's just using the database adapter – psycopg2 in our case – in its default PEP-249-compliant mode), and you can commit that transaction with session. commit() or roll it back with session.


1 Answers

If you're using SQLAlchemy's connection pooling, then what you're seeing is probably the automatic rollback that happens when a connection is closed after use. It's apparently necessary to guarantee that the connection is 'clean' for the next time it's pulled out of the pool. See this page for more info; search for 'pooling mechanism' near the top.

From what I recall (it's been a couple years since I last worked with this) changing the isolation level to autocommit won't solve the problem, since it won't see the SELECT statement as requiring a commit.

You really just want to wrap that statement in a transaction. I don't know how your code is structured, but you should just be able to use SQLAlchemy's connection.begin and connection.commit. You could even just execute the BEGIN and COMMIT as arbitrary SQL.

like image 142
DNS Avatar answered Sep 19 '22 21:09

DNS