SQLAlchemy和SQLite:数据库被锁定

时间:2012-12-15 18:57:32

标签: python sqlite python-2.7 sqlalchemy

我有一个使用最新sqlalchemy的python脚本。 当我使用sqlite时,只有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()

11 个答案:

答案 0 :(得分:15)

SQLite在对数据库进行写入时锁定数据库,例如在发送UPDATE,INSERT或DELETE时。使用ORM时,这些将在flush上发送。在存在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

答案 1 :(得分:4)

您应该在线程中的所有对象中使用单个会话。 sqlite真的不喜欢多个连接,而sqlalchemy实际上是每个会话的连接(看起来你可能每个类都有一个会话,这意味着在一个线程中有多个会话)。

答案 2 :(得分:3)

sqlite数据库一次只允许一个进程访问它。也许你有一个使用数据库的独立过程?

答案 3 :(得分:2)

我遇到了同样的错误,我可以通过以下方式修复:

db.session.close_all()

对我来说,错误是由于打开的数据库连接太多,因为我使用的是 Spyder 控制台而不是终端

答案 4 :(得分:0)

检查您的代码以获取这些要点:

  1. MyDb的实例必须是所有应用程序生命周期的实例。 MyDb必须是单身人士。
  2. 尝试对引擎使用“普通”策略,但不使用pool_threadlocal=True
  3. 完成每个逻辑请求的关闭会话。
  4. 例如:

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

答案 5 :(得分:0)

通过任何开发人员工具检查数据库中所有未决的提交。

正如上面每个人都说的,sqlite数据库一次只允许一个进程访问它。在我的情况下,我正在使用数据库浏览器进行sqlite 操作,但与此同时,我没有提交查询。这也锁定了数据库,并且不允许应用程序写入数据库。

答案 6 :(得分:0)

就我而言,逻辑很简单,没有多线程,问题的根源似乎很平庸...

  

'SQLite不是为高级别的写并发而设计的。的   数据库本身(作为文件)在写入过程中被完全锁定   交易中的操作,恰好意味着一个“连接” (在   现实中的文件句柄)在此期间对数据库具有独占访问权限   在此期间-在此期间,所有其他“连接”将被阻止   时间。

...以便“启发”一个想法:断开我在工作期间用来检查数据库的数据库浏览器。 而且效果很好。 因此,如果这是您的情况-检查您是否未通过其他工具连接到sqlite;)

答案 7 :(得分:0)

我的答案仅适用于那些正在使用flask数据库并且准备删除其数据库以删除数据库锁的用户。如果您正在尝试,那么可以肯定的是,您可以通过运行python脚本再次向表中添加数据。

我们在这里....

  1. 删除烧瓶项目中存在的data.sqlite文件

  2. 删除烧瓶项目中存在的迁移文件夹

  3. 现在运行以下命令来创建新数据库:

    • 烧瓶db初始化
    • 烧瓶db migration -m“表”
    • 烧瓶数据库升级
  4. 现在您可以运行python脚本将数据添加到数据库中,或者可以 使用python promt / flask shell手动将数据添加到表中。

答案 8 :(得分:0)

也遇到了相同的问题:

java.lang.NullPointerException
    at org.deeplearning4j.nn.modelimport.keras.layers.KerasInput.<init>(KerasInput.java:103)
    at org.deeplearning4j.nn.modelimport.keras.layers.KerasInput.<init>(KerasInput.java:83)
    at org.deeplearning4j.nn.modelimport.keras.KerasSequentialModel.<init>(KerasSequentialModel.java:120)
    at org.deeplearning4j.nn.modelimport.keras.KerasSequentialModel.<init>(KerasSequentialModel.java:57)
    at org.deeplearning4j.nn.modelimport.keras.utils.KerasModelBuilder.buildSequential(KerasModelBuilder.java:322)
    at org.deeplearning4j.nn.modelimport.keras.KerasModelImport.importKerasSequentialModelAndWeights(KerasModelImport.java:223)
    at NeuralNetwork.<init>(NeuralNetwork.java:17)
    at Main.setup(Main.java:35)
    at processing.core.PApplet.handleDraw(PApplet.java:2412)
    at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
    at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:316)

最后,到达这里,因为我只是打开了另一个终端,打开了sqlite3文件,所以在关闭窗口后,它就可以了!

答案 9 :(得分:0)

只需使用StaticPool。并遵循以下答案(scoped_session):https://stackoverflow.com/a/9621251

create_engine(DB_PATH, echo=False, poolclass=StaticPool, connect_args={'check_same_thread': False})

答案 10 :(得分:0)

如果表中有重复的记录,可能会发生这种情况