Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sqlalchemy explicit locking of Postgresql table

I'm trying to explicitly lock a postgres table using this sqlalchemy command:

db.engine.execute('BEGIN; LOCK TABLE database_version IN ACCESS EXCLUSIVE MODE;')

After this executes, if I go into the database client and run:

select * from pg_catalog.pg_locks;

There aren't any ACCESS EXCLUSIVE locks present.

If instead, I run the first command, but from inside the db client, it works as expected.

Is there a reason trying to get a table lock from sqlalchemy isn't working correctly?

Ideally, I want only one process to be able to query from and insert into the database_version table at a time.

like image 671
Andrew Avatar asked May 19 '16 18:05

Andrew


People also ask

Do Postgres transactions lock the table?

PostgreSQL locks often called “write locks” or “exclusive locks,” restrict users from modifying a row or a PostgreSQL table's contents. Rows that have undergone a DELETE or UPDATE operation will be locked solely until the transaction is finished.

How do I lock a table in PostgreSQL?

We can lock the table by using access share, row share, row exclusive, share, share update exclusive, exclusive, share row exclusive, and access exclusive mode in PostgreSQL. Using the lock command we need to specify the table name and the name of the mode which was we have applied on the table.

Can SQLAlchemy be used with PostgreSQL?

This SQLAlchemy engine is a global object which can be created and configured once and use the same engine object multiple times for different operations. The first step in establishing a connection with the PostgreSQL database is creating an engine object using the create_engine() function of SQLAlchemy.


1 Answers

So it turns out that I needed to start a nested transaction from the session object instead of trying to BEGIN one using straight SQL.

db.session.begin_nested()
db.session.execute('LOCK TABLE database_version IN ACCESS EXCLUSIVE MODE;')

Then, i insert the new row:

new_version = DatabaseVersion(version=version + 1)
db.session.add(new_version)
db.session.commit()

and then finally commit again to close out the nested transaction:

db.session.commit()
like image 159
Andrew Avatar answered Sep 23 '22 09:09

Andrew