SQLAlchemy 与显式锁定

18 投票
1 回答
28099 浏览
提问于 2025-04-17 13:39

我有多个进程可能会往数据库里插入重复的行。这些插入操作并不是很频繁(每小时几次),所以性能不是特别关键。

我尝试在插入之前先检查一下是否已经存在,比如这样:

#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()

我遇到的问题是,exist() 检查并不会锁定表格,因此可能会有多个进程同时尝试插入相同的对象。在这种情况下,一个进程成功插入了,而其他进程则会因为完整性错误(IntegrityError)而失败。虽然这样也能工作,但我觉得这并不“干净”。

我真的希望能有一种方法,在进行 exists() 检查之前先锁定 Camera 表。

1 个回答

11

也许这个对你会有帮助:

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

你可以通过直接执行SQL语句来锁定表。我不太确定在Elixir中是怎样的,但在普通的SQLAlchemy中,大概是这样的:

 conn = engine.connect()
 conn.execute("LOCK TABLES Pointer WRITE")
 #do stuff with conn
 conn.execute("UNLOCK TABLES")

撰写回答