2012-12-15 162 views
4

我有一個使用最新的sqlalchemy的python腳本。 當我使用SQLite,只sqlite的,其他分貝效果很好,我得到以下錯誤:SQLAlchemy和SQLite:數據庫被鎖定

sqlalchemy.exc.OperationalError: (OperationalError) database is locked u'SELECT blabla.... 

任何提示?從我的代碼(簡化)

例如,我有幾種方法這樣,選擇,更新和刪除的東西:

class MyDb(object): 
    def __init__(self): 
     engine = create_engine("sqlite:///file", poolclass=NullPool, pool_threadlocal=True) 
     engine.pool_size=1 
     engine.pool_timeout = 60 
     self.sess = sessionmaker(bind=engine) 

    def del_stuff(self): 
     sess = self.sess() 
     sess.query(Stuff).delete() 
     try: 
      sess.commit() 
     except: 
      sess.rollback() 

    def set_stuff(self, id, bar): 
     sess = self.sess() 
     sess.query(Foo).get(id).bar = bar 
     try: 
      sess.commit() 
     except: 
      sess.rollback() 

回答

2

SQLite數據庫只允許一個進程在同一時間訪問它。也許你有一個單獨的過程使用數據庫?

+0

沒有,只有一個進程。 – tapioco123

0

檢查你的代碼爲以下幾點:

  1. MYDB的實例必須是一個對所有的應用程序生命週期。 MyDb必須是單身人士。
  2. 嘗試使用'純文本'引擎策略,但不是pool_threadlocal=True
  3. 關閉每個邏輯請求的會話完成。

例如:

def set_stuff(self, id, bar): 
    sess = self.sess() 
    sess.query(Foo).get(id).bar = bar 
    try: 
     sess.commit() 
    except: 
     sess.rollback() 
    finally: 
     sess.close() 
4

你應該在一個線程中使用跨所有對象的單個會話。 sqlite確實不喜歡多個連接,而sqlalchemy實際上是每個會話的連接(它看起來像你可能有一個每個類的會話,這意味着在單個線程中有多個會話)。

7

SQLite在寫入數據庫時​​會鎖定數據庫,例如發送UPDATE,INSERT或DELETE時。當使用ORM時,這些會在刷新時發送。數據庫將保持鎖定狀態,直到出現COMMIT或ROLLBACK。

在多線程情況下,我最常看到「數據庫已鎖定」錯誤。一個線程將鎖定數據庫,另一個線程將嘗試寫入自己的數據庫。如果第一個線程沒有在超時期限內釋放鎖定(默認4-5秒,如果我記得),則第二個線程上會產生OperationalError。

它可能會非常棘手知道什麼時候沖洗,因此寫的對數據庫所做如果會話具有autoflush=True(默認設置),因爲任何查詢將導致齊平。在SQL日誌有時轉彎可以幫助澄清時,事情正在發生:

logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) 

有一些相關的文件在這裏:http://docs.sqlalchemy.org/en/rel_0_9/dialects/sqlite.html#database-locking-behavior-concurrency