2010-05-16 2 views
3

파이썬과 sqlite에 관계없이이 오류가 발생합니다.SQLite에서 (다른 테이블에서) 페치하는 동안 행 삽입

File "addbooks.py", line 77, in saveBook 
    conn.commit() 
    sqlite3.OperationalError: cannot commit transaction - SQL statements in progress 

코드는 다음과 같습니다

conn = sqlite3.connect(fname) 
cread = conn.cursor() 

cread.execute('''select book_text from table''') 
while True: 
    row = cread.fetchone() 
    if row is None: 
     break 
    .... 
    for entry in getEntries(doc): 
     saveBook(entry, conn) 

가 fetchall 할 수 없습니다

() 테이블 및 열 크기가 큰, 그리고 메모리가 부족하기 때문이다.

더티 트릭을 사용하지 않고 수행 할 수있는 작업은 다음과 같습니다 (메모리에 ROWID를 가져 오는 것, 적합 할 것 같은 행을 하나씩 선택하는 것)?

답변

1

는 알 수없는 경우 "더러운 속임수"너무 ;-)

이 문제에 대한 나의 해결책은 SELECT... LIMIT clause을 사용하는 것입니다

, 당신이 가정하는 기본 키 정수 필드 id

current_id = 0 
while True:  
    cread.execute('''select book_text from table where id > %s limit 2''' % current_id) 
    results = cread.fetchall() 
    if results is None: 
     break; 
    for row in results: 
     ... (save book) ... 
     current_id = row.id 
+0

그래, 조금 까다 롭다. :-) – Samuel

2

등이 수 문제는 자동 커밋 모드에서 연결을 유지했다는 것입니다. 모든 트랜잭션을 하나의 트랜잭션으로 처리하면 모든 업데이트를 완료 한 후에 만 ​​커밋이 수행되므로 모든 트랜잭션이 정상적으로 처리되어야합니다.

+0

연결이 자동 커밋 모드가 아니며, 명시 적으로 isolation_level을 설정하려고 시도했지만 동일한 문제가 발생합니다. saveBooks 내에 "부분 롤백"이 있기 때문에 처리가 끝날 때마다 하나의 커밋을 수행하는 것은 불가능합니다. 왜냐하면 전체 작업이 아니라 일부 변경 사항 만 롤백해야하기 때문입니다 (그리고 아마 저에게 커밋을 허용하지 않으면 ' t는 "롤백"하자) – Samuel

+0

@ Samuel : [SAVEPOINT] (http://www.sqlite.org/lang_savepoint.html)를 사용해 볼 수 있습니다. *는 * 일종의 반 - 경로 체크 포인트입니다.하지만 나는 그들을 한번도 시도한 적이 없다는 것을 경고하며, 그래서 나는 그들에 관해 읽은 것을 조금 밖에 알지 못한다. –

0

문제는 연결에 대해 하나 이상의 활성 커서가 없어야한다는 것입니다.

해결 방법은 업데이트에 대한 새 연결을 사용하는 것입니다.

불행히도 내가 읽은 곳의 정확한 위치를 기억하지 못하기 때문에 그것을 증명할 수 없습니다.

UPD :

다음 코드는 내 Windows XP에서 작동 :

results: 
---------- 
0 updated 
1 updated 
2 updated 
3 updated 
4 updated 

것은 내가의에 conn2.commit()를 이동하는 경우 :

import sqlite3 
import os 
conn1 = sqlite3.connect('test.db') 
cursor1 = conn1.cursor() 
conn2 = sqlite3.connect('test.db') 
cursor2 = conn2.cursor() 


cursor1.execute("CREATE TABLE my_table (a INT, b TEXT)") 
cursor1.executemany("INSERT INTO my_table (a, b) VALUES (?, NULL);", zip(range(5))) 
conn1.commit() 

cursor1.execute("SELECT * FROM my_table") 
for a, b in cursor1: 
    cursor2.execute("UPDATE my_table SET b='updated' WHERE a = ?", (a,)) 

conn2.commit() 

print "results:" 
print 10 * '-' 
cursor1.execute("SELECT * FROM my_table") 
for a, b in cursor1: 
    print a, b 
cursor1.close() 
conn1.close() 
cursor2.close() 
conn2.close() 
os.unlink('test.db') 

그리고 반환 예상대로 다음 루프, 내가 언급 한 것과 같은 오류가 발생합니다 :

Traceback (most recent call last): 
    File "concurent.py", line 16, in <module> 
    conn2.commit() 
sqlite3.OperationalError: database is locked 

따라서 해결책은 각 줄 다음에 커밋하는 대신 끝에서 한 번 커밋하는 것입니다.

+0

나는 또한 그것을 시도했다. 그러나 "데이터베이스가 잠겨있다"는 오류 또는 이와 유사한 것이있다. 어쨌든, 나는 hackish 해결책을 가지고 가고 계속 전진했다. – Samuel

+0

@ Samuel : 답을 예제로 업데이트했습니다. – newtover

관련 문제