SQLite3是否安全处理多个进程的并发访问 读/写从相同的DB?有什么平台例外吗?
当前回答
当您为db指定名称时,如果您有并发访问(特别是写),甚至在内存db中指定名称时,很自然会得到这个结果。 在我的例子中,我使用Sqlite进行测试,这是因为在同一个解决方案中有几个测试。 你可以有两个改进:
在创建db.Database.EnsureDeletedAsync(); 使用空字符串进行连接,在这种情况下,每次调用都会创建一个随机名称:
{
"ConnectionStrings": {
"ConnectionType": "sqlite",
"ConnectionString": ""
}
}
其他回答
是的。 让我们来看看为什么
SQLite是事务性的
SQLite中单个事务中的所有更改都可能发生 完全或根本没有
这种ACID支持以及并发读/写是通过两种方式提供的——使用所谓的日志记录(我们称之为“旧方式”)或预写日志记录(我们称之为“新方式”)
日志(旧方式)
在这种模式下,SQLite使用数据库级锁定。 这是需要理解的关键。
这意味着当它需要读/写一些东西时,它首先在整个数据库文件上获得一个锁。 多个阅读器可以共存并并行阅读
在写入过程中,它确保获得一个排他锁,并且没有其他进程同时读写,因此写入是安全的。
这就是为什么这里说SQlite实现了可序列化的事务
麻烦
由于它每次都需要锁定整个数据库,每个人都在等待一个处理写入的进程,并发性受到影响,这种并发写/读的性能相当低
回滚/中断
在向数据库文件写入内容之前,SQLite首先会将要更改的块保存在一个临时文件中。如果在写入数据库文件的过程中发生了崩溃,它将拾取这个临时文件并恢复其中的更改
预写测井或WAL(新方法)
在这种情况下,所有写操作都被追加到一个临时文件(预写日志),并且该文件定期与原始数据库合并。 当SQLite搜索某些东西时,它会首先检查这个临时文件,如果没有发现,则继续检查主数据库文件。
因此,读者不会与作者竞争,与旧的方式相比,表现要好得多。
警告
SQlite在很大程度上依赖于底层的文件系统锁定功能,因此应该谨慎使用,更多细节请点击这里
你也可能会遇到数据库锁定错误,特别是在日志模式下,所以你的应用程序需要在设计时考虑到这个错误
如果大多数并发访问是读(例如SELECT), SQLite可以很好地处理它们。但是如果开始并发地编写,锁争用就会成为一个问题。这在很大程度上取决于您的文件系统有多快,因为SQLite引擎本身非常快,并且有许多巧妙的优化来最小化争用。尤其是SQLite 3。
对于大多数台式机/笔记本电脑/平板电脑/手机应用程序,SQLite已经足够快了,因为没有足够的并发性。(Firefox在书签、历史记录等方面广泛使用SQLite)
对于服务器应用程序,前段时间有人说过,在典型的场景下(例如博客、论坛),SQLite数据库可以完美地处理每天少于10万的页面浏览量,我还没有看到任何相反的证据。事实上,使用现代磁盘和处理器,95%的网站和web服务都可以很好地使用SQLite。
如果你想要快速的读/写访问,请使用内存中的SQLite数据库。内存比磁盘快几个数量级。
似乎没有人提到WAL(预写日志)模式。确保事务被正确组织,并设置了WAL模式,当人们在更新时读取数据时,没有必要保持数据库锁定。
唯一的问题是,在某些情况下,WAL需要重新合并到主数据库中,并且在到数据库的最后一个连接关闭时这样做。对于一个非常繁忙的网站,你可能会发现需要几秒钟才能关闭所有连接,但每天10万次点击应该不是问题。
2019年,有两个新的并发写选项尚未发布,但在不同的分支中可用。
"PRAGMA journal_mode = wal2"
与常规的“wal”模式相比,这种日志模式的优点是,写入者可以继续写入一个wal文件,而另一个则是检查点。
BEGIN CONCURRENT -链接到详细的文档
The BEGIN CONCURRENT enhancement allows multiple writers to process write transactions simultanously if the database is in "wal" or "wal2" mode, although the system still serializes COMMIT commands. When a write-transaction is opened with "BEGIN CONCURRENT", actually locking the database is deferred until a COMMIT is executed. This means that any number of transactions started with BEGIN CONCURRENT may proceed concurrently. The system uses optimistic page-level-locking to prevent conflicting concurrent transactions from being committed.
它们一起出现在begin-concurrent-wal2中,或者各自出现在一个独立的分支中。
是的,SQLite处理并发性很好,但从性能角度来看它并不是最好的。据我所知,没有例外。详情见SQLite的网站:https://www.sqlite.org/lockingv3.html
这句话很有趣:“寻呼机模块确保所有更改都同时发生,要么所有更改都发生,要么都不发生,两个或多个进程不会试图同时以不兼容的方式访问数据库。”
推荐文章
- Mac SQLite编辑器
- SQLite:如何将查询结果保存为CSV文件?
- SQLite中“如果不存在,请插入”语句
- 转义单引号字符用于SQLite查询
- 如何创建默认值“现在”的时间戳列?
- 如何检索插入id后插入行在SQLite使用Python?
- 创建存储过程和SQLite?
- SQLite并发访问
- 如何连接字符串与填充在sqlite
- 在Android SQLite中处理日期的最佳方法
- SQLite数据库文件使用什么扩展名重要吗?
- 无法加载DLL 'SQLite.Interop.dll'
- 快速简单的方法迁移SQLite3到MySQL?
- 在Ubuntu上安装sqlite3-ruby错误
- sqlite3。ProgrammingError:提供的绑定数量不正确。当前语句使用1,并提供了74个