SQLiteOpenHelper 单连接与多连接
Posted
技术标签:
【中文标题】SQLiteOpenHelper 单连接与多连接【英文标题】:SQLiteOpenHelper single connection vs multiple connections 【发布时间】:2018-01-15 14:46:45 【问题描述】:我对访问SQLiteDatabase
感到非常困惑。它应该是一个连接或多个连接才能从多个线程进行访问。我读过很多文章,包括以下两篇。
https://***.com/a/3689883/3027124 http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking
这两个都建议使用单一连接。甚至我自己对同一问题的回答也被 OP 接受了。我使用Singleton
方法访问SQLiteopenHelper
类。
https://***.com/a/35358702/3027124
但是在阅读了enableWriteAheadLogging
的文档后我仍然感到困惑
此方法可以并行执行来自多个 同一数据库上的线程。它通过打开多个 连接到数据库并使用不同的数据库连接 对于每个查询。数据库日志模式也更改为启用 写入与读取同时进行。
现在这是令人困惑的部分。如果我想同时从多个线程访问数据库,我可以通过Singleton
访问SQLiteOpenHelper
,这在我的理解中意味着插入的串行执行,而同时读取可以无错误地完成。但是上面的文档说,为了同时访问,应该调用enableWriteAheadLogging
,这会返回创建多个连接。这是怎么回事??如果我通过在多个线程中使用Singleton SQLiteOpenHelper
调用getWritableDatabase()
来进行插入,这意味着什么?电话会是串行的吗?应该调用enableWriteAheadLogging
吗?
请澄清。
【问题讨论】:
您需要SQLiteDatabase#enableWriteAheadLogging 的用例是什么? “开始事务”或“sql-insert/update/delete”上的默认(无预写日志记录)阻止进一步读/写线程,直到事务执行完成,所以这应该是线程安全的。 【参考方案1】:在处理线程时,无论我是否使用enableWriteAheadLogging
,我都会使用单例实例,这在大多数应用程序中都是如此,除非它是一个非常微不足道的应用程序,例如示例。
使用单例实例可确保线程安全:单例实例可确保跨该实例进行同步,这意味着当您有读取和写入方法从不同线程同时调用数据库时,其中一个应该等待另一个,因为数据库在写入时被锁定。
很明显,这是文档中所写并在下面引用的情况
它不是 数据库上可能同时发生读取和写入 时间。在修改数据库之前,writer 隐式获取一个 数据库上的排他锁,阻止读者访问 数据库,直到写入完成。
enableWriteAheadLogging
实际上正在改变上述行为,因为上述语句仅在未启用预写日志记录时为真(默认)。
那么当您通过enableWriteAheadLogging
启用预写日志记录时会发生什么?
它实际上是在更改默认行为以启用实际的并行性,因为它更改了底层数据库日志文件以启用同时进行写入和读取,但要做到这一点,它需要比平时更多的内存。阅读下面的文档报价以了解更多信息!
相反,当启用预写日志记录时(通过调用此 方法),写操作发生在一个单独的日志文件中,它允许 读取以同时进行。在写入过程中,读者 在其他线程上将按原样感知数据库的状态 在写开始之前。写入完成后,其他阅读器 然后线程将感知数据库的新状态。
每当数据库出现时启用预写日志记录是个好主意 将被多个线程同时访问和修改 同时。但是,预写式日志记录使用显着更多的内存 比普通的日记,因为有多个连接到 同一个数据库。所以如果一个数据库只被一个线程使用, 或者如果优化并发不是很重要,那么预写 日志记录应该被禁用。
【讨论】:
我正在使用Singleton
,但我的意思是,如果我使用enableWriteAheadLogging
并同时从多个线程调用getWritableDatabase
,这不应该是一个问题,因为有多个连接而不是单个?
是的,没有问题,这是由数据库内部处理的,因为有一个连接池,在设置WAL时会启动***.com/questions/29062967/…以上是关于SQLiteOpenHelper 单连接与多连接的主要内容,如果未能解决你的问题,请参考以下文章
zookeeper的c API 单线程与多线程问题 cli_st和cli_mt