SQLite替代并发写作(Delphi)

时间:2012-02-13 17:11:49

标签: database delphi sqlite concurrency

(在WAL模式下使用Delphi 2010 +最新的SQLite)

我正在使用DISQLite(SQLite的Delphi端口)和我的多线程客户端应用程序(尚未发布,所以如果我真的必须)

我的分析师清楚地说这是一个愚蠢的决定,我将其跟踪到2-3个非常简单的SQL语句,这些语句在单线程应用程序中执行时会飞,但因为线程锁定/等待(SQLite实际上并不能很好地执行多个线程试图同时写入)

我尽最大努力优化我的代码/避免瓶颈,但经过几周的努力,我现在想知道转储SQLite&选择不同的数据库引擎(?)

我的要求是:

  1. ACID
  2. 非常好的同步阅读/写作(记录级别)支持
  3. (非常)快速&稳定的数据库引擎
  4. B树
  5. Delphi 2010支持
  6. 我只使用带索引的基本INSERT / UPDATE / DELETE命令,没什么特别的。所以我的SQL要求是相对基本的(我不需要加入或其他“更高级”的sql东西)。

    我也对NQL解决方案持开放态度,只要它支持上述要求。

    我的研究导致了Berkley DB,如果我理解正确的话,它是一个带有并发写入支持的SQLite的修改版本,但问题是它不适用于delphi。

    我也读过有关京都议定书的内容,但是再一次,没有delphi的支持:(

    任何建议都非常受欢迎,

    谢谢!

6 个答案:

答案 0 :(得分:3)

如果符合以下条件,您的申请速度是多少:

  • 您只为所有线程使用一个数据库连接;
  • 使用全局关键部分保护数据库连接访问。

然后你可以尝试我们的Sqlite3 static binding,它是在没有线程互斥的情况下编译的:

#define SQLITE_THREADSAFE 2
//  assuming multi-thread safety is made by caller - in our framework, there is
// only one thread using the database connection at the same time, but there could
// be multiple database connection at the same time (previous was 0 could be unsafe)
#define SQLITE_OMIT_SHARED_CACHE 1
// no need of shared cache in a threadsafe calling model

我们在mORMot ORM框架中使用这样的模型,并且与四级缓存相关联:

  • 语句缓存,用于重用SQL语句和动态绑定参数;
  • 数据库级别的全局JSON结果缓存,在任何INSERT / UPDATE上刷新全局;
  • 在服务器端指定的表或记录的CRUD / RESTful级别调整记录缓存;
  • 在客户端指定表或记录的CRUD / RESTful级别调整记录缓存。

产生的性能一点都不差 - 它在多线程访问中可以很好地扩展,即使是全局关键部分也是如此。当然, SQlite3 的设计规模不如Oracle!但是我在实际应用程序中使用了SQlite,有很多客户端。您可以考虑使用 FireBird ,它具有更复杂(和调整)的客户端服务器架构。

关于提高写作速度,您可以将您的作品分组到一个事务中,然后它会更快。这是我使用for speed-up writing并且您可以使用多个客户端扩展此概念:在服务器端,您将写入重新组合到共享事务中,该事务将在超时期限(例如一秒)后提交。

SQLite3对于这样的添加非常快(对于带有绑定参数的准备好的INSERT语句,甚至更多),但对于单个添加来说速度很慢,因为它必须使用低级API锁定整个文件,这非常慢。为了使其成为ACID,请确保始终处理提交。实际上,其他数据库引擎在后台隐藏的类似过程中实现了良好的并发速度。 SQLite3默认写入方法应该是这样的,以确保从多个进程访问同一文件 - 但在您的客户端 - 服务器应用程序中,您可以依赖于您将是唯一一个访问SQLite3数据库文件,因此它将是安全的。

答案 1 :(得分:2)

像Firebird DB的嵌入式版本会有什么帮助吗?

FirbirdSQL.org Downloads Page

我过去曾成功使用过它。

答案 2 :(得分:1)

只需将您的表(可以同时编写)拆分为单独的SQLite数据库文件,并使用您的主连接将它们attach一起分开。

答案 3 :(得分:0)

这是我的观点:

Absolute Database是一个不错的选择。

答案 4 :(得分:0)

NexusDB可以做到这一切,Embedded Version is free。它支持德尔福作为一等公民。

答案 5 :(得分:0)

FWIW,我终于决定坚持DISQLite以及这个"丑陋",hackish,解决方案:

  • 进行了一些(不那么微小的)更改,以尽可能减少对线程内DB的写入(每个线程需要两个DB插入)

  • 当我绝对在线程内部工作时必须向DB写入内容时,我采用了SQL查询参数&将它们写在一个特殊的文件夹中(写入文件非常快),即

C:\我的项目\未决-SQL \ insert_SOME-GUID.txt

每个文件都如下所示:

参数1 |参数2 |参数3 | Param4 |

  • 一旦我完成了线程(或者我的应用程序崩溃),我调用了一个扫描此文件夹的例程,解压缩SQL参数并使用预准备语句运行它们(包含在事务中)。

  • 任何包含少于4个参数的文件都会被视为已损坏且会被跳过。

这是一个hackish丑陋的算法(对我来说很羞耻!),但是它有效,它很快,有点ACID,我不知道#39; t必须花费数月时间学习另一个可能(或可能不适合)的数据库引擎。

我只是想感谢大家的帮助,时间压力使我无法切换到另一个数据库引擎,至少对于这个项目而言。