ContentProvider相关_沙漠一只雕得儿得儿的博客-CSDN博客_contentprovider线程安全
1、如果是单进程多线程,多线程访问数据库的时候会出现这样的异常,Sqlite 自身是不支持多线程同时操作的
- java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed .
-
- 或 java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase : 或 java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:
很简单,直接用多线程锁就可以
2、如果是多进程呢:sqlite多进程多连接经常死锁。设计上就不是干这事的。
SQLite的并发性允许多个进程一次打开数据库文件,并允许多个进程一次读取数据库。当任何进程想要写入时,它必须在更新期间锁定整个数据库文件。但这通常只需要几毫秒。其他流程只是等待作者完成然后继续他们的业务。其他嵌入式SQL数据库引擎通常只允许单个进程一次连接到数据库。
多进程写sqlite的实验:sqlite3的进程安全访问测试_LostSpeed的博客-CSDN博客
sqlite3同一个表无法由2个进程同时读写表记录。
总有一个进程会出现“database is locked”的报错,去查了资料。大概意思是:因为是文件型数据库,无法使2个进程同时向同一个文件写数据。我的应用是一个读(读完一条记录删一条),一个写,应该会触发sqlite的文件读写锁吧。
尝试sql执行失败后重试,倒是可以继续跑。但是每一个SQL都有可能失败,都要重试。这执行效率就下来了。
3、多线程同时往数据库插入数据
现在我们有Thread 1
和Thread 2
两个线程要往数据库中插入数据:
那么我们可能会收到下如下错误logcat
,并且其中一个线程的插入写数据库操作将会执行失败:
android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
为什么会发生 SQLiteDatabaseLockedException 异常呢?
因为每一次我们新创建new
一个SQLiteOpenHelper
对象,都会新建立一个数据库连接database connection
。如果同时用两个不同的connection
往数据库中写数据,其中一个将会失败,并收到database is locked
异常。
如何确保多线程先使用的是同一个数据库连接database connection
?
使用单例类。
SQLite 与线程
SQLite 是线程安全的。
线程模型
SQLite 支持如下三种线程模型
设置线程模型
SQLite 可以通过以下三种方式进行线程模型的设置,在实际应用中选择任一一项都可以。
SQLite 并发和事务
事务
事务是 SQLite 的核心概念。对数据库的操作 (绝大部分) 会被打包成一个事务进行提交,需要注意的是,这里的打包成事务是自动开启的。举例而言,如果简单在一个 for 循环语句里向数据库中插入 10 条数据,意味着将自动生成 10 个事务。但需要注意的是事务是非常耗时的,一般而言, SQLite 每秒能够轻松支持 50000 条的数据插入,但是每秒仅能够支持几十个事务。一般而言,事务速度受限于磁盘速度。所以在批量插入时需要考虑禁用自动提交,将其用 BEGIN ... COMMIT 打包成一个事务。
锁和并发
SQLite 通过五种锁状态来完成事务。
一个线程只有拥有低级别锁时才能够获得更高一级的锁