2009-10-22 5 views
2

많은 커밋을 신속하게 수행 할 때 sqlite3 연산 오류

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가 0이 아닌 기회가있는 것 같습니다. 그것은 다소 데이터베이스와 관련된 데이터와 관련이있는 것 같지만 문제가 무엇인지 판단 할 수 없습니다.

대부분의 경우 모든 데이터를 읽고 한 번만 커밋하면 오류가 발생하지 않습니다.

다음은 내 컴퓨터에서 실행 된 샘플의 끝입니다.

  ? 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 

Mac OS X 10.5를 사용하고 있습니다. .8 내장 파이썬 2.5.1 및 Sqlite3 3.4.0.

답변

2

이름의 "라이트"부분에서 알 수 있듯이 sqlite3은 가벼운 데이터베이스 사용을위한 것이지 빅 보이 (Big Boys)와 같이 대규모 확장 성 동시성이 아닙니다. 여기에서 일어나고있는 것은 당신이

그래서 다른 요청을 할 때 sqlite가 요청한 마지막 변경을 작성 완료되지 않았 음을 것을 나에게 보인다, 내가 당신을 위해 볼 수있는 몇 가지 옵션은 다음과 같습니다

  1. 당신은 많은 보낼 수 학습에 대한 대략적인 시간 file locking, concurrency, and transaction in sqlite3
  2. this Reddit post에서 제안한 것처럼 앱이 첫 번째 오류 발생 후 작업을 다시 시도하도록하면 오류 방지 기능을 추가 할 수 있습니다. 여기에는 "코드에 효과적인 메커니즘이있는 경우 단순히 다시 시도해보십시오. 대부분의 sqlite 동시성 문제는 사라집니다. "및"전달 isolation_level = None은 연결할 것입니다. x it "입니다.
  3. 당신은 PostgreSQL

같은 확장 성 데이터베이스를 사용하도록 전환 할 수 있습니다 (내 돈은, # 2, # 3은 갈 수있는 방법입니다.)

+0

내가이 시도에 커밋 넣고 잡은 sqlite3.OperationalError 예외가 발생하여 최대 10 번 재 시도합니다. 안돼. 그런 다음 isolation_level = None (2 번에서 언급했듯이)을 사용하여 연결을 호출했는데 그 점이 훌륭하게 작동했습니다. 감사. –

+0

우수! 다행히 도울 수 있습니다 : D – ewall

+0

저는 매우 늦었지만, 확장 성이 뛰어난 데이터베이스를 사용하는 것이 좋습니다. 원격으로 큰 테이블이나 데이터베이스에서 SQL Server와 같은 것으로 전환하는 것만으로도 성능이 향상됩니다. – TimothyAWiseman

관련 문제