0%

SQLite并发

SQLite支持多线程吗?

SQLite支持多线程,但是是有条件的支持,也就是:

  • 同一个连接不能在多线程中使用,不同连接才可以在多线程中使用,这个是最宏观的SQLite多线程准则。
  • SQLite的文件锁是粗颗粒的,也就是以数据库文件为维度加锁,涉及到5种锁状态。

为了确保数据库安全,SQLite 内部抽象了两种类型的互斥锁(锁的具体实现和宿主平台有关)来应对线程并发问题:

  • fullMutex
    可以理解为 connection mutex,和连接句柄(上问描述的 sqlite3 结构体)绑定。
    保证任何时候,最多只有一个线程在执行基于连接的事务。
  • coreMutex
    当前进程中,与文件绑定的锁。
    用于保护数据库相关临界资源,确保在任何时候,最多只有一个线程在访问。

SQLite三种线程模型

  • single-thread
    • coreMutex 和 fullMutex 都被禁用。
    • 用户层需要确保在任何时候只有一个线程访问 API,否则抛出异常。
  • multi-thread
    • coreMutex 保留,fullMutex 禁用。
    • 可以多个线程基于不同的连接并发访问数据库,但单个连接在任何时候只能被一个线程访问。
    • 单个 connection,如果并发访问,会抛出异常。
      • 报错信息:illegal multi-threaded access to database connection。
  • serialized
    • coreMutex 和 fullMutex 都保留。

同一个数据库连接多线程访问会有什么问题?

一个数据库连接对应一个事务操作,多线程访问一个连接会造成事务不原子化,事务执行结果会混乱。

不同的连接同时写数据库会发生什么?

就走入了SQLite本身的锁机制。

写数据会去获取保留锁、独占锁。

如果还有连接要写入,就会返回SQLITE_BUSY。

Android中的SQLite的Thread Mode是什么?

SQLite官网说默认线程模式是serialized

Android的SQLiteDatabase类的setLockingEnabled(boolean lockingEnabled)文档说,默认线程模式是Multi-thread。

API 16 setLockingEnabled() 方法又废弃了。

不管怎么说肯定不是single-thread,不是multi-thread就是serialized。

参考:
What is the Default Threading mode of SQLite in Android?