sqlite3.dylib: illegal multi-threaded access to database connection

后端 未结 4 1600
[愿得一人]
[愿得一人] 2021-01-02 08:40

I have an iOS app that uses sqlite3 and I\'m facing issues with multi-threading crashing the app with the illegal multi-threaded access to database connec

相关标签:
4条回答
  • 2021-01-02 09:17

    In case of any one faced this problem in Swift. Solution will be:

    let dbName = "first.db"
    static let shared = DatabaseManger()
    var db: OpaquePointer?
    
    
    private init(){
        print("singletone initialized")
        sqlite3_shutdown();
        let dbPath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            .appendingPathComponent(dbName)
        if sqlite3_open_v2(dbPath.path, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX, nil) == SQLITE_OK {
            print("Successfully opened database connection at \(dbPath.path)")
        }
        else {
            print("unable to open database connection")
        }
    }
    

    This code tested in swift version 4.0 and 4.2

    0 讨论(0)
  • 2021-01-02 09:22

    Use please SQLite Shared-Cache Mode https://www.sqlite.org/sharedcache.html

    sqlite3_open_v2(path.path, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE, nil) != SQLITE_OK

    SQLITE_OPEN_SHAREDCACHE

    Reliable 100% :)

    0 讨论(0)
  • 2021-01-02 09:24

    It turns out that SQLITE_CONFIG_MULTITHREAD mode works well on a multi-threading environment as long as you don't use the same connection simultaneously; which happen to be the exact scenario that I had. Therefore, to solve this issue you can either open a new connection for each thread or use SQLITE_CONFIG_SERIALIZED in full mutex mode using SQLITE_OPEN_FULLMUTEX flag to open the connection.

    The helper method ended up like so:

    +(sqlite3*) getInstance {
      if (instance == NULL) {
        sqlite3_shutdown();
        sqlite3_config(SQLITE_CONFIG_SERIALIZED);
        sqlite3_initialize();
    
        NSLog(@"isThreadSafe %d", sqlite3_threadsafe());
    
        const char *path = [@"./path/to/db/db.sqlite" cStringUsingEncoding:NSUTF8StringEncoding];
    
        if (sqlite3_open_v2(path, &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX, NULL) != SQLITE_OK) {
          NSLog(@"Database opening failed!");
        }
      }
    
      return instance;
    }
    
    0 讨论(0)
  • 2021-01-02 09:32

    From https://www.sqlite.org/threadsafe.html

    SQLite supports three different threading modes:

    Single-thread. In this mode, all mutexes are disabled and SQLite is unsafe to use in more than a single thread at once.

    Multi-thread. In this mode, SQLite can be safely used by multiple threads provided that no single database connection is used simultaneously in two or more threads.

    Serialized. In serialized mode, SQLite can be safely used by multiple threads with no restriction.

    In iOS,SQLite default threading mode was SQLITE_OPEN_NOMUTEX(equal to Multi-thread),which was not safe when multiple threads write or read the database simultaneously use one connection. Change threading mode to serialized may helpful for you.You can change threading mode use sqlite3_config() or sqlite3_open_v2().

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