如何在Python中使用sqlite3连接

时间:2014-08-01 23:34:12

标签: python sqlite

我创建了以下WebApp.test()来测试对数据库的并发访问,以模拟在后台任务更新数据库时执行某些查询的浏览器。

执行使用相同连接的新查询时后台任务崩溃。我做错了什么?

@cherrypy.expose
def test(self, x=''):

    if x == 'connect':
        WebApp.con = sqlite3.connect('db', check_same_thread=False)
        return 'connected'

    if x == 'insert':
        with WebApp.con: 
            cur = WebApp.con.cursor()
            cur.execute('drop table if exists x')
            cur.execute('create table x(x)')
            for i in range(10000):
                cur.execute('insert into x values (%s)' % i)
                WebApp.con.commit()
        return 'Inserted %s rows' % i

    if x == 'query': 
        with WebApp.con: 
            cur = WebApp.con.cursor()
            cur.execute('select * from x where x < 20')
            data = cur.fetchall()
        return 'result: %s' % data

我按顺序导航到以下3个页面,每个页面之间只需几秒钟:

test?x=connect
test?x=insert
test?x=query

第一个创建连接。

第二个开始一个非常长的周期,模拟在服务器上运行几分钟的后台作业。

第三个进行简单查询。

当我导航到第三页时,查询结果按预期返回,但仍在运行的循环因以下错误而中断:

    WebApp.con.commit()
sqlite3.OperationalError: cannot commit - no transaction is active

2 个答案:

答案 0 :(得分:0)

一个问题是您在每种情况下都使用连接对象作为上下文管理器。 docs提到连接将在最后提交或回滚。无论如何,你都明确地提交了它(几乎否定了使用上下文管理器开始的任何好处)。

因此,您的第三个查询会提交连接,这会导致您的insert脚本出现问题,因为现在已经提交了连接。 (...或者甚至是你在10000次迭代循环中所做的显式提交)

Sqlite也mentions,你不能在线程之间共享连接和游标。我想你每次都想使用新的连接。

来自connect方法的docs&#34;当多个连接访问数据库,并且其中一个进程修改数据库时,SQLite数据库将被锁定,直到提交该事务为止。 timeout参数指定连接在引发异常之前等待锁定消失的时间。 timeout参数的默认值为5.0(五秒)。&#34;

答案 1 :(得分:0)

经过一番研究后,我得出以下结论:

不可能同时在不同的线程中使用相同的连接。这两个线程将共享相同的事务,相同的游标和其他资源。

可以在不同的线程中使用相同的连接(不是同时)。例如,SqlAlchemy使用连接池。

在简单的Web应用程序(如我的)中,可以在每次调用时创建一个连接,但开销很小。