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。