0

I'm working on an application which uses Flask, SQLAlchemy and PostgreSQL. I've to write a transaction that executes multiple queries on the database.

def exec_query_1():
    with db.engine.connect() as connection:
        connection.execute(#some-query)

def exec_query_2():
    with db.engine.connect() as connection:
        connection.execute(#some-query)

def exec_query_3():
    with db.engine.connect() as connection:
        connection.execute(#some-query)

def execute_transaction():
    with db.engine.connect() as connection:
        with connection.begin() as transaction:
            exec_query_1()
            exec_query_2()
            exec_query_3()

Given that the application is multithreaded, will this code work as expected? If yes, how? If no, what would be the right approach to make it work?

1 Answer 1

5

The code will not work as expected, even in a single thread. The connections opened in the functions are separate1 from the connection used in execute_transaction() and have their own transactions. You should arrange your code so that the functions receive the connection with the ongoing transaction as an argument:

def exec_query_1(connection):
    connection.execute(#some-query)

def exec_query_2(connection):
    connection.execute(#some-query)

def exec_query_3(connection):
    connection.execute(#some-query)

def execute_transaction():
    with db.engine.connect() as connection:
        with connection.begin() as transaction:
            exec_query_1(connection)
            exec_query_2(connection)
            exec_query_3(connection)

Remember that connections are not thread-safe, so don't share them between threads. "When do I construct a Session, when do I commit it, and when do I close it?" is a good read, altough about Session.

1 May depend on pool configuration.

Sign up to request clarification or add additional context in comments.

4 Comments

Why do you need the transaction alias in with connection.begin() as transaction? Upvoted the answer because of the brilliant explanation but can't seem to wrap my head around where transaction is used. Learning sql so pardon the ignorance
It's not needed, prolly just wrote it like that out of habit. with connection.begin(): would work just as well.
I'm also learning sqlalchemy and Python3 (as I go, just enough to do a quick database server). In the above example, when does the "commit" occur? In particular, if one of those calls to execute a query raises an exception, will that be sufficient to rollback the transaction or do you need to catch that exception and manually rollback?
COMMIT automatically happens on returning the transaction at the exit of with connection.begin() block

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.