关于数据库:具有并发写入功能的SQLite替代方法(Delphi)

SQLite alternative with concurrent writing (Delphi)

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

我正在将DISQLite(SQLite的Delphi端口)用于我的多线程客户端应用程序(尚未发布,因此,如果确实需要,我可以更改数据库引擎)。

我的探查器清楚地表明这是一个愚蠢的决定,我将其跟踪到2-3个在单线程应用程序中执行时会飞行的非常简单的SQL语句,但是由于线程锁定/等待(SQLite确实不会在尝试同时编写的多个线程中表现良好)

我已尽力优化代码/避免出现瓶颈,但是经过数周的辛苦工作,我现在想知道转储SQLite是否不仅更容易


如果满足以下条件,您的申请速度是多少?

  • 您的所有线程仅使用一个数据库连接;
  • 您可以通过全局关键节来保护数据库连接访问。

然后您可以尝试我们的Sqlite3静态绑定,该绑定是在没有线程互斥锁的情况下编译的:

1
2
3
4
5
6
#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,它具有用于客户端-服务器的更复杂(且经过调整)的体系结构。

关于加快写作速度,您可以将您的写作分组为一个事务,这样会更快。这就是我用于加速写入的方法,您可以将这个概念扩展到多个客户端:在服务器端,您将写入重新分组为共享事务,该事务将在超时时间(例如一秒钟)后提交。铅>

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


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

FirbirdSQL.org下载页面

过去我已经成功地使用了它。


只需将表(可以同时写入)拆分成单独的SQLite数据库文件,然后使用主连接将它们全部附加在一起。


FWIW,我最终决定坚持使用DISQLite以及这种"丑陋"的,有点拙劣的解决方案:

  • 进行一些(不太重要)更改,以最大程度地减少对线程内部DB的写入(每个线程需要两个DB插入)

  • 当我在线程内部工作时绝对必须向DB写一些东西时,我采用了SQL查询参数


    NexusDB可以完成所有操作,而嵌入式版本是免费的。它支持Delphi作为头等公民。


    这是我的观点:

    绝对数据库是一个很好的选择。