SQLite3和多个进程

当多个进程访问单个SQLite数据库文件时,如何确保正确性?

首先,避免并发访问sqlite数据库文件。 并发是sqlite的弱点之一,如果你有一个高度并发的应用程序,请考虑使用另一个数据库引擎。

如果您无法避免并发或删除sqlite,请将您的写入事务包装在BEGIN IMMEDIATE; …… END; 。 sqlite中的默认事务模式是DEFERRED ,这意味着仅在第一次实际写入尝试时获取锁定。 使用IMMEDIATE事务,会立即获取锁定,或者立即获得SQLITE_BUSY 。 当某人持有对数据库的锁定时,其他锁定尝试将导致SQLITE_BUSY

处理SQLITE_BUSY是您必须自己决定的事情。 对于许多应用程序,等待一两秒然后重试工作完全正常,在n尝试失败后放弃。 有一些sqlite3 API助手使这很容易,例如sqlite3_busy_handler()sqlite3_busy_timeout()但它也可以手动完成。

您还可以使用操作系统级别同步来获取数据库的互斥锁,或使用操作系统级别的线程间/进程间消息传递来指示一个线程何时完成访问数据库。

如果任何SQLite原语尝试访问其他进程正在同时访问的数据库,则它将返回SQLITE_BUSY。 您可以检查该错误代码,然后重复操作。

或者,您可以使用操作系统同步 – MS Windows上的互斥锁或其他操作系统上的类似操作。 该过程将尝试获取互斥锁,如果其他人已经拥有该互斥锁,则该进程将被阻塞,直到另一个进程完成操作并释放互斥锁。 应该注意防止进程获取mutext然后永不释放它的情况。

基本上,您需要使用事务包装数据访问代码。 这将使您的数据保持一致。 不需要其他任何东西。

在SQLite中你正在使用

开始交易

提交交易

用于分隔您的交易。 将SQL代码置于其间,以使其在单个事务中执行。

但是,正如之前的人在我之前评论过 – 你需要密切关注并发问题。 如果用于读取访问,SQLite可以合理地快速工作(多个读取器未被阻止并且可以并发运行)。

但是 – 如果您的代码交错写入和读取访问,则图片会发生相当大的变化。 使用SQLite – 即使单个编写器处于活动状态,您的整个数据库文件也将被锁定。

关于这一点的SQLite FAQ