Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy and explicit locking

I have multiple processes that can potentially insert duplicate rows into the database. These inserts do not happen very frequently (a few times every hour) so it is not performance critical.

I've tried an exist check before doing the insert, like so:

#Assume we're inserting a camera object, that's a valid SQLAlchemy ORM object that inherits from declarative_base...
try:
  stmt = exists().where(Camera.id == camera_id)
  exists_result = session.query(Camera).with_lockmode("update").filter(stmt).first()

  if exists_result is None:
    session.add(Camera(...)) #Lots of parameters, just assume it works
    session.commit()
except IntegrityError as e:
  session.rollback()

The problem I'm running into is that the exist() check doesn't lock the table, and so there is a chance that multiple processes could attempt to insert the same object at the same time. In such a scenario, one process succeeds with the insert and the others fail with an IntegrityError exception. While this works, it doesn't feel "clean" to me.

I would really like some way of locking the Camera table before doing the exists() check.

like image 723
CadentOrange Avatar asked Jan 25 '13 10:01

CadentOrange


People also ask

Does SQLAlchemy automatically close connection?

connect() method returns a Connection object, and by using it in a Python context manager (e.g. the with: statement) the Connection. close() method is automatically invoked at the end of the block.

Is SQLAlchemy Engine thread safe?

Every pool implementation in SQLAlchemy is thread safe, including the default QueuePool . This means that 2 threads requesting a connection simultaneously will checkout 2 different connections. By extension, an engine will also be thread-safe.

Does commit close the Session SQLAlchemy?

commit() will then COMMIT the actual database transaction or transactions, if any, that are in place. Finally, all objects within the Session are expired as the transaction is closed out.

What is Create_engine in SQLAlchemy?

The create_engine() method of sqlalchemy library takes in the connection URL and returns a sqlalchemy engine that references both a Dialect and a Pool, which together interpret the DBAPI's module functions as well as the behavior of the database.


1 Answers

Pehaps this might be of interest to you:

https://groups.google.com/forum/?fromgroups=#!topic/sqlalchemy/8WLhbsp2nls

You can lock the tables by executing the SQL directly. I'm not sure what that looks like in Elixir, but in plain SA it'd be something like:

 conn = engine.connect()
 conn.execute("LOCK TABLES Pointer WRITE")
 #do stuff with conn
 conn.execute("UNLOCK TABLES")
like image 170
AlexVhr Avatar answered Sep 20 '22 09:09

AlexVhr