2009-06-08 4 views
9

누구든지이 오류에 대한 입력을 제공 할 수 있습니까? Objective C를 사용하여 테이블에 삽입하려고합니다.SQLite 예외 : SQLite 통화 중

이 작업을 수행하는 동안 SQLite Busy 오류가 발생합니다. 왜 이런 일이 일어나는거야?

+0

몇 가지 예제 코드를 제공 할 수 있습니까? 일어나는 일들을 이해하기위한 몇 줄. – stefanB

답변

7

제대로 작동하면 "사용 중"은 잠금을 얻을 수 없음을 의미합니다. 일부 다른 프로세스 (또는 스레드 등)가 데이터베이스에 잠금을 가졌다 고합니다. sqlite3를 기능을 오류 코드 SQLITE_BUSY를 호출 할 때 결과로 얻을 경우 DB가 같은 프로세스 또는 프로세스 내에서 하나 개의 스레드에 의해 잠겨되었음을 drdaeman에 의해 관찰

File Locking And Concurrency In SQLite Version 3

19

, 이것은 의미한다.

이 상황을 처리하는 올바른 방법은 루프에서 작업을 시도하고 반환 코드가 여전히 SQLITE_BUSY 인 경우 잠시 기다렸다가 (시간 제한 값 결정) 다음 작업을 다시 시도하는 것입니다 루프 반복. 에 의해

int numberOfRetries = 0; 
BOOL retry   = NO; 

if (!pStmt) { 
    do { 
     retry = NO; 
     rc  = sqlite3_prepare(db, [sql UTF8String], -1, &pStmt, 0); 

     if (SQLITE_BUSY == rc) { 
      retry = YES; 
      usleep(20); 

      if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) { 
       NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]); 
       NSLog(@"Database busy"); 
       sqlite3_finalize(pStmt); 
       [self setInUse:NO]; 
       return nil; 
      } 
     } 
     else if (SQLITE_OK != rc) { 


      if (logsErrors) { 
       NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); 
       NSLog(@"DB Query: %@", sql); 
       if (crashOnErrors) { 

        NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); 
       } 
      } 

      sqlite3_finalize(pStmt); 

      [self setInUse:NO]; 
      return nil; 
     } 
    } 
    while (retry); 
} 

:

는 예를 들어, 다음 코드는 목표 C 래퍼 FMDB에서 가져온 것입니다 (http://code.google.com/p/flycode/source/browse/trunk/fmdb는) 쿼리가 일부 작업이 SQLITE_BUSY를 반환 할 수 있음을 고려에 대한 성명을 준비하는 방법을 보여줍니다 당신이 sqlite에 접근 할 필요가 있다면, FMDB는 네이티브 C API를 통한 직접 접근과 관련하여 매우 편리하고 훨씬 간단합니다.

+6

[sqlite3_busy_timeout] (http://www.sqlite.org/c3ref/busy_timeout.html)을 호출하여 거의 동일한 결과를 얻을 수 있습니다. –

+1

Downvoted. 첫째, 어떤 오픈 소스 프로젝트 에서조차도 누군가가 일을하고 있다면, 그것이 "적절한 일"이라는 것을 의미하지는 않는다. 정말로 적절한 것은 문제의 도서관 저자가 문서화 한 내용입니다. http://www.sqlite.org/c3ref/busy_handler.html –

+0

@ Alaksiej N : 댓글에 제공 한 바쁜 처리기에 대한 설명서를주의 깊게 읽었습니까? 읽는 중 : "바쁜 처리기가 있어도 잠금 경합이있을 때이 핸들러가 호출 될 것이라고 보장 할 수는 없습니다. 바쁜 처리기를 호출하면 교착 상태가 발생할 수 있다고 SQLite에서 판단하면 SQLITE_BUSY 또는 SQLITE_IOERR_BLOCKED가 호출됩니다 바쁜 처리기. " 따라서 SQLite가 항상 정의한 통화 중 처리기를 호출한다는 보장은 없습니다! –

7

순차적 INSERT INTO 명령에서 SQLITE_BUSY와 비슷한 문제점이있었습니다. 첫 번째 행은 ok로 삽입되었지만 응용 프로그램이 두 번째 행을 삽입하려고하면 SQLITE_BUSY 상태가됩니다. Google을 둘러 본 후, 문을 실행 한 후에 sqlite3_finalize()를 호출해야한다고 배웠습니다 : http://www.sqlite.org/c3ref/finalize.html. 내 진술을 마무리 내 문제가 해결되었습니다.

4

필자의 경우, 사용 후 데이터베이스를 닫는 것을 잊어 버렸습니다. 고정 된 내 다음 :

sqlite3_finalize(statement); 
sqlite3_close(contactDB); 

FMDB

도 쉽게에서 이러한 두통을 완화 할 수 있습니다.

0

관리자 권한으로 명령 프롬프트를 실행하는 것만 큼 간단합니다. 또는 UNIX에서 데이터베이스를 시작할 때 sudo을 사용할 수 있습니다.