SQLite Exception: SQLite Busy

前端 未结 5 1863
青春惊慌失措
青春惊慌失措 2020-11-27 22:40

Can anyone provide any input on this error. I am trying to insert into table using Objective C.

While I am doing this, I am getting an error SQLite Busy. Why this is

相关标签:
5条回答
  • 2020-11-27 23:25

    I had a similar problem with SQLITE_BUSY on sequential INSERT INTO commands. The first row inserted ok, but when the app tried to insert a second row, I got the SQLITE_BUSY status. After Google'ing around, I learned you must call sqlite3_finalize() on statements after executing them: http://www.sqlite.org/c3ref/finalize.html. Finalizing my statements fixed my problem.

    0 讨论(0)
  • 2020-11-27 23:26

    If I get it right, "busy" means that you cannot obtain a lock. Seems that some another process (or thread, etc) has a lock on a database.

    File Locking And Concurrency In SQLite Version 3

    0 讨论(0)
  • 2020-11-27 23:27

    If you get as a result when invoking an sqlite3 function the error code SQLITE_BUSY, this means as observed by drdaeman that the db has been locked by the same process or by one thread within your process.

    The proper way to deal with this situation is to try the operation in a loop, and if the return code is still SQLITE_BUSY, to wait for some time (you decide the timeout value) and then retry the operation in the next loop iteration.

    For instance, the following code snippet is taken from the Objective C wrapper FMDB (http://code.google.com/p/flycode/source/browse/trunk/fmdb) shows how to prepare a statement for a query taking into account that some operations may return 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);
    }
    

    By the way, if you need to access sqlite, FMDB is very handy and much simpler to use with respect to direct access through the native C APIs.

    0 讨论(0)
  • 2020-11-27 23:32

    I know this is late, but if anyone is looking for a more detailed explanation on why the error occurs, please have a look at https://www.activesphere.com/blog/2018/12/24/understanding-sqlite-busy. I wrote this, hoping it might help people understand concurrency in SQLite better.

    It covers different scenarios under which the error might occur, in different SQLite modes (Rollback journal and WAL primarily). It also looks at ways to correctly handle such errors (retries with busy_timeout might not always succeed, also manually re-trying individual queries might lead to a deadlock).

    0 讨论(0)
  • 2020-11-27 23:35

    In my case, I had forgotten to close database after using it. Following fixed mine:

    sqlite3_finalize(statement);
    sqlite3_close(contactDB);
    

    FMDB can also alleviate these headaches from you easily.

    0 讨论(0)
提交回复
热议问题