2024-12-14 08:00:07

SQLite并发访问

SQLite3是否安全处理多个进程的并发访问 读/写从相同的DB?有什么平台例外吗?


当前回答

是的,SQLite处理并发性很好,但从性能角度来看它并不是最好的。据我所知,没有例外。详情见SQLite的网站:https://www.sqlite.org/lockingv3.html

这句话很有趣:“寻呼机模块确保所有更改都同时发生,要么所有更改都发生,要么都不发生,两个或多个进程不会试图同时以不兼容的方式访问数据库。”

其他回答

如果大多数并发访问是读(例如SELECT), SQLite可以很好地处理它们。但是如果开始并发地编写,锁争用就会成为一个问题。这在很大程度上取决于您的文件系统有多快,因为SQLite引擎本身非常快,并且有许多巧妙的优化来最小化争用。尤其是SQLite 3。

对于大多数台式机/笔记本电脑/平板电脑/手机应用程序,SQLite已经足够快了,因为没有足够的并发性。(Firefox在书签、历史记录等方面广泛使用SQLite)

对于服务器应用程序,前段时间有人说过,在典型的场景下(例如博客、论坛),SQLite数据库可以完美地处理每天少于10万的页面浏览量,我还没有看到任何相反的证据。事实上,使用现代磁盘和处理器,95%的网站和web服务都可以很好地使用SQLite。

如果你想要快速的读/写访问,请使用内存中的SQLite数据库。内存比磁盘快几个数量级。

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中,或者各自出现在一个独立的分支中。

似乎没有人提到WAL(预写日志)模式。确保事务被正确组织,并设置了WAL模式,当人们在更新时读取数据时,没有必要保持数据库锁定。

唯一的问题是,在某些情况下,WAL需要重新合并到主数据库中,并且在到数据库的最后一个连接关闭时这样做。对于一个非常繁忙的网站,你可能会发现需要几秒钟才能关闭所有连接,但每天10万次点击应该不是问题。

当您为db指定名称时,如果您有并发访问(特别是写),甚至在内存db中指定名称时,很自然会得到这个结果。 在我的例子中,我使用Sqlite进行测试,这是因为在同一个解决方案中有几个测试。 你可以有两个改进:

在创建db.Database.EnsureDeletedAsync(); 使用空字符串进行连接,在这种情况下,每次调用都会创建一个随机名称:

{
  "ConnectionStrings": {
    "ConnectionType": "sqlite",
    "ConnectionString": ""
  }
}

是的,SQLite处理并发性很好,但从性能角度来看它并不是最好的。据我所知,没有例外。详情见SQLite的网站:https://www.sqlite.org/lockingv3.html

这句话很有趣:“寻呼机模块确保所有更改都同时发生,要么所有更改都发生,要么都不发生,两个或多个进程不会试图同时以不兼容的方式访问数据库。”