sqlite3操作快速执行多次提交时出错

时间:2009-10-22 21:42:50

标签: python sqlite

我得到了

sqlite3.OperationalError: SQL logic error or missing database

当我运行一个应用程序时,我一直在努力。接下来是一个缩小但完整的样本,它为我展示了问题。此示例使用两个表;一个用于存储用户,另一个用于记录外部目录系统中的用户信息是否是最新的。 (可以想象,在我的实际应用程序中,表格相当长)。该示例创建了一组随机用户,然后浏览(随机)用户列表并将其添加到第二个表中。

#!/usr/bin/env python

import sqlite3
import random

def random_username():
    # Returns one of 10 000 four-letter placeholders for a username
    seq = 'abcdefghij'
    return random.choice(seq) + random.choice(seq) + \
           random.choice(seq) + random.choice(seq)

connection = sqlite3.connect("test.sqlite")

connection.execute('''CREATE TABLE IF NOT EXISTS "users" (
    "entry_id"              INTEGER PRIMARY KEY AUTOINCREMENT  NOT NULL ,
    "user_id"               INTEGER NOT NULL ,
    "obfuscated_name"       TEXT NOT NULL)''')
connection.execute('''CREATE TABLE IF NOT EXISTS "dir_x_user" (
    "user_id"               INTEGER PRIMARY KEY NOT NULL)''')        

# Create a bunch of random users
random.seed(0)  # get the same results every time
for i in xrange(1500):
    connection.execute('''INSERT INTO users
        (user_id, obfuscated_name) VALUES (?, ?)''',
        (i, random_username()))
connection.commit()

#random.seed()
for i in xrange(4000):
    username = random_username()
    result = connection.execute(
        'SELECT user_id FROM users WHERE obfuscated_name = ?',
        (username, ))
    row = result.fetchone()
    if row is not None:
        user_id = row[0]
        print "  %4d %s" % (user_id, username)
        connection.execute(
            'INSERT OR IGNORE INTO dir_x_user (user_id) VALUES(?)',
            (user_id, ))
    else:
        print "     ? %s" % username
    if i % 10 == 0:
        print "i = %s; committing" % i
        connection.commit()
connection.commit()

特别需要注意的是接近结束的行,

if i % 10 == 0:

在实际应用程序中,我正在查询来自网络资源的数据,并希望不时地提交用户。发生错误时更改该行会发生变化;看来,当我提交时,OperationalError有一个非零的机会。它似乎与我在数据库中放入的数据有些相关,但我无法确定问题所在。

大多数情况下,如果我读取所有数据然后只提交一次,则不会发生错误。 [是的,那里有明显的解决方法,但潜在的问题仍然存在。]

以下是我的计算机上运行示例的结束:

     ? cgha
i = 530; committing
     ? gegh
     ? aabd
     ? efhe
     ? jhji
     ? hejd
     ? biei
     ? eiaa
     ? eiib
     ? bgbf
   759 bedd
i = 540; committing
Traceback (most recent call last):
  File "sqlitetest.py", line 46, in <module>
    connection.commit()
sqlite3.OperationalError: SQL logic error or missing database

我正在使用内置Python 2.5.1和Sqlite3 3.4.0的Mac OS X 10.5.8。

1 个答案:

答案 0 :(得分:2)

正如名称中的“精简版”部分所暗示的那样,sqlite3用于轻量级数据库使用,而不是像一些大男孩那样的大规模可扩展并发。在我看来,这里发生的事情是sqlite还没有写完你提出另一个请求时你要求的最后一次更改

所以,我看到的一些选项是:

  1. 你可以花很多时间学习file locking, concurrency, and transaction in sqlite3
  2. 您可以根据this Reddit post上的某些人的建议,让您的应用在第一次失败后重试操作,添加更多防错功能,其中包括“如果代码具有简单有效机制的提示”再次尝试,大多数sqlite的并发问题消失了“和”传递isolation_level =无连接似乎解决了它。“
  3. 您可以切换到使用更具伸缩性的数据库,例如PostgreSQL
  4. (对于我的钱,#2或#3是要走的路。)