我的應用程序正在使用作用域會話和SQLALchemy的聲明式樣式。這是一個web應用程序,許多數據庫插入由Celery
執行,一個任務調度程序。在插入SQLAlchemy(聲明式)時處理重複的主鍵
通常情況下,決定插入的對象時,我的代碼可能會做大致如下的內容:
from schema import Session
from schema.models import Bike
pk = 123 # primary key
bike = Session.query(Bike).filter_by(bike_id=pk).first()
if not bike: # no bike in DB
new_bike = Bike(pk, "shiny", "bike")
Session.add(new_bike)
Session.commit()
這裏的問題是,由於很多,這是通過異步的工人來做,有可能爲一個雖然插入Bike
與id=123
,而另一個正在檢查其存在,但工作中途中斷。在這種情況下,第二個worker將嘗試使用相同的主鍵插入一行,並且SQLAlchemy將引發一個IntegrityError
。
我不能爲我的生活找到一個很好的方式,從換出Session.commit()
除了解決這個問題:
'''schema/__init__.py'''
from sqlalchemy.orm import scoped_session, sessionmaker
Session = scoped_session(sessionmaker())
def commit(ignore=False):
try:
Session.commit()
except IntegrityError as e:
reason = e.message
logger.warning(reason)
if not ignore:
raise e
if "Duplicate entry" in reason:
logger.info("%s already in table." % e.params[0])
Session.rollback()
然後我到處有Session.commit
我現在有schema.commit(ignore=True)
哪裏我不不介意該行不再被插入。
對我來說這似乎非常脆弱,因爲字符串檢查。正如一個供參考,當IntegrityError
提高它看起來像這樣:
(IntegrityError) (1062, "Duplicate entry '123' for key 'PRIMARY'")
所以當然是我被插入主鍵是像Duplicate entry is a cool thing
話,我想我可能會錯過IntegrityError
的這實際上不是因爲重複的主鍵。
是否有更好的方法,它保持我用乾淨的SQLAlchemy的方法(而不是開始寫出來的字符串等語句。)
Db的是MySQL的(儘管單元測試我喜歡使用SQLite,並不想用任何新方法來阻止這種能力)。
乾杯!
你爲什麼不考慮使用自動遞增爲您生成主鍵?那麼你不必擔心這個問題。 還是有沒有這樣做的具體原因? – mata 2012-04-25 19:40:39
有一個特定的原因(對不起,這個例子有點瑣碎)。 – Edwardr 2012-04-25 19:50:37