2009-06-08 22 views
9

誰でもこのエラーで入力できます。 Objective Cを使用してテーブルに挿入しようとしています。SQLite例外:SQLite Busy

私はこれをやっている間に、エラーSQLite Busyを取得しています。なぜこれが起こっているのですか?

+0

いくつかのコード例を提供できますか?何が起こっているのかを理解するための行のカップル。 – stefanB

答えて

7

私が正しいとすれば、「ビジー」とはあなたがロックを得ることができないことを意味します。いくつかの別のプロセス(またはスレッドなど)がデータベースをロックしているようです。

File Locking And Concurrency In SQLite Version 3

19

あなたが結果として取得した場合、エラーコードSQLITE_BUSY sqlite3の機能を呼び出すときに、これはDBがあなたのプロセス内で同じプロセスによって、または1つのスレッドによってロックされていることをdrdaemanによって観察されるような意味。

この状況に対処する適切な方法は、ループ内で操作を試みることです。戻りコードがSQLITE_BUSYのままの場合は、しばらく待ってから(タイムアウト値を決定します)、次の操作を再試行してくださいループ反復。例えば

、次のコードスニペットは、対物CラッパーFMDB(http://code.google.com/p/flycode/source/browse/trunk/fmdb)から取得され、いくつかの操作が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); 
} 

あなたが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_BUSYまたはSQLITE_IOERR_BLOCKEDビジーハンドラ。したがって、あなたが定義したビジーハンドラをSQLiteが常に起動するという保証はありません! –

7

SQL INSERT INTOコマンドでSQLITE_BUSYと同様の問題が発生しました。最初の行は正常に挿入されましたが、アプリケーションが2番目の行を挿入しようとすると、SQLITE_BUSYステータスを取得しました。 Googleの周りを回った後、文を実行した後に文のsqlite3_finalize()を呼び出さなければならないことを学んだ。http://www.sqlite.org/c3ref/finalize.html。私の声明を完成させることで私の問題は解決しまし

4

私の場合は、使用後にデータベースを閉じるのを忘れていました。固定された鉱山、以下:

sqlite3_finalize(statement); 
sqlite3_close(contactDB); 

FMDB

も簡単にあなたからこれらの頭痛を軽減することができます。

0

私の管理者としてコマンドプロンプトを実行するのと同じくらい簡単でした。 UNIXの場合は、データベースを起動するときにsudoを使用することもできます。

関連する問題