线程并发数据库查询是否安全?

时间:2012-12-06 22:51:21

标签: c# sqlite concurrency thread-safety

我正在努力改进我为工作而写的这个程序。最初我很匆忙,他们不关心表演或任何事情。因此,我做出了一个可怕的决定来查询整个数据库(一个SQLite数据库),然后将结果存储在列表中以供我的函数使用。但是,我现在正在考虑将每个函数都线程化,并让函数只查询它需要的数据库部分。有~25个功能。我的问题是,这样做安全吗?此外,是否可以拥有多个并发连接?我只会从数据库中提取信息,永远不会插入或更新。

3 个答案:

答案 0 :(得分:0)

我向他描述的方式 [*] 是让每个并发线程打开自己与数据库的连接,因为每个连接一次只能处理一个查询或修改。然后,具有连接的线程组可以轻松地执行并发读取。如果许多并发写入导致严重问题导致过多的阻塞或无法获取锁定,那么你就会超出SQLite为你做的事情(并且应该考虑像PostgreSQL这样的基于服务器的数据库)

请注意,如果更方便的话,你也可以让一个主线程打开工作线程的连接,但是建议(为了你的理智,如果没有别的!)只实际使用每个连接来自一个主题。


[*对于SQLite的正常构建。当然,可以在构建时关闭它。]

答案 1 :(得分:0)

SQLite没有写入并发,但它支持任意多个同时读取的连接。 只需确保每个线程都有自己的连接。

答案 2 :(得分:0)

25个同时连接不是一个聪明的主意。这是一个巨大的数字。

我经常为这个问题创建一个多层设计。我通过一种具有内部缓存的ObjectFactory类将所有请求发送到数据库。 ObjectFactory会将请求转发给ConnectionPoolHandler,并将结果存储在其缓存中。此连接池处理程序使用X个并发连接,但将它们分派给多个线程。

但是,在应用此设计之前必须做一些评论。首先要问自己以下两个问题:

  • 您的应用程序是否是唯一可以访问此应用程序的应用程序 数据库?
  • 您的应用程序是唯一修改此数据库中数据的应用程序吗?

如果第一个问题是否定的,那么您可能会遇到锁定问题。如果你的第二个问题被否定回答,那么应用缓存将非常困难。您甚至可能不希望实现任何缓存。

如果您经常根据唯一引用(例如主键)请求对象,则缓存尤其有用。在这种情况下,您可以将最常用的对象存储在Map中。一个流行的缓存集合是“LRUMap”(“最近最少使用”地图)。这个系列的好处是它可以自动将最常用的对象排列到顶部。同时它具有最大尺寸,并自动从地图中删除很少使用的项目。

缓存的第二个优点是每个对象只存在一次。例如:

  1. 从数据库中提取员工。
  2. ObjectFactory将结果集转换为实际的对象实例
  3. ObjectFactory立即将其存储在缓存中。
  4. 稍后,一群员工使用SQL“......其中的名称如”John%“声明。
  5. 在将结果集转换为对象之前,ObjectFactory首先检查这些记录的ID是否已经存储在缓存中。
  6. 找到了匹配!啊哈,这个对象不需要重新创建。
  7. 在内存中只有一个特定对象有几个优点。

    最后但并非最不重要的是Java中存在类似“弱引用”的内容。这些引用实际上可以被垃圾收集器清理。我不确定它是否存在于C#中以及它是如何被调用的。通过实现这一点,您甚至不必关心缓存对象的最大数量,您的垃圾收集器将负责处理它。