将数据从多个线程写入SQLite的最佳方法

3
我正在创建一个监控应用程序。我想从所有服务器读取查询并将其存储在sqlite文件中。只要需要就显示它。我使用c++编写此应用程序-从多个服务器获取和存储数据到单个sqlite数据库。我使用单独的线程从多个服务器获取数据。如果直接获取并将数据写入sqlite,那么它可能会锁定sqlite文件,因为100多个线程将同时进行写入。 如何以最佳方式从多个线程向sqlite写入数据?

1
X-Y问题解决方案:考虑使用selectepoll、Overlapped IO或其它操作系统最佳支持的IO多路复用器来减少线程数量。 - user4581301
我编辑了我的问题。我无法减少线程计数,它取决于连接的服务器数量。 - sandra kevin
1
没错,但是使用多路复用器,一个线程可以管理多个服务器。 - user4581301
2
为了加强 user4581301 的评论,记住那些多个服务器的所有网络流量都通过计算机上的单个网络接口传输。虽然看起来你在多个线程中同时访问多个服务器,但由于这一切都发生在你的网络上,因此访问是串行的。因此,一个单独的线程可以像多个线程一样轻松处理几个服务器连接。 - bazza
1
我也强烈建议您重新考虑user4581301的评论。谷歌搜索“c10k问题”。您可能误用了线程。 - Ami Tavory
3个回答

3

如果您无法控制同时写入操作的数量,我认为使用sqlite没有更好的方法。

SQLite并不适用于您的用例。考虑切换到客户端/服务器关系型数据库管理系统。这也是SQLite建议的做法:

https://www.sqlite.org/whentouse.html


客户端/服务器关系数据库系统更适合的情况

客户端/服务器应用程序

如果有许多客户端程序通过网络发送SQL到同一个数据库,则使用客户端/服务器数据库引擎,而不是SQLite。SQLite可以在网络文件系统上工作,但由于大多数网络文件系统所带来的延迟,性能并不好。此外,在许多网络文件系统实现中(包括Unix和Windows),文件锁定逻辑存在错误。如果文件锁定无法正常工作,则两个或多个客户端可能会尝试同时修改同一数据库的同一部分,导致损坏。由于这个问题是由底层文件系统实现中的错误造成的,因此SQLite无法防止它。

一个好的经验规则是避免在同一个数据库将直接访问(没有介入应用程序服务器)且同时从许多计算机上进行访问的情况下使用SQLite。

(...)

高并发

SQLite支持无限数量的同时读取者,但它只允许一个写入者在任何时刻。对于许多情况来说,这不是问题。编写者排队等待。每个应用程序快速完成其数据库工作并继续执行,没有锁定持续时间超过几十毫秒。但是,有些应用程序需要更高的并发性,这些应用程序可能需要寻找不同的解决方案。


1
你可以使用消息队列,如RabbitMQ或Redis来解决这类问题。
1. 将你的数据发送到队列中,这对异步插入非常有用。 2. 创建一个工作线程,该线程将从队列中取出新的消息。 3. 使用该工作线程将新的消息插入SQLite中。
采用这种架构,只有一个工作线程将写入数据库,并且不会出现锁定问题,因为SQLite可以在“一个写者多个读者”模式下工作。

-3

使用一个sqlite数据库连接来为所有线程服务,连接时设置标志 SQLITE_OPEN_FULLMUTEX。 这样,数据库将对所有线程的写操作进行序列化,从而避免锁定。 但是您需要调整数据库和应用程序的设计,使写入查询足够快,满足需求。


FULLMUTEX是最具锁定性的,而不是没有锁定。它仅影响连接对象,无论出于何种原因,您都不应该在线程之间共享连接对象(每个线程应该拥有自己的连接)。 - Colonel Thirty Two
对于数据库写操作,最终总是会锁定表行和/或表页,这可能导致死锁。建议只有一个数据库写线程/进程或使用FULLMUTEX。 更好的做法是,写入相同表格的线程应该具有锁定功能,而写入不同表格的线程则不需要。 对于读操作,不需要串行化,它们可以并行运行。 - BJovke
SQLite使用单个锁来控制整个数据库,不存在死锁的可能性。再次强调,FULLMUTEX保护连接对象,这个对象不应该在线程之间共享,因为这会使得使用事务变得不可能。 - Colonel Thirty Two
你的回答与问题本身相矛盾。问题是:“如何在多个线程中向SQLite写入数据的最佳方法?”因此,你的评论“连接对象不应该在线程之间共享”与问题要求的相矛盾。在这种情况下,需要从多个线程访问,并且实现这一点的唯一安全方式是使用互斥锁。 - BJovke
2
每个线程应该有自己的连接。您可以对同一个数据库拥有多个连接。这些连接将处理事务锁定。 - Colonel Thirty Two

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接