从开箱即用的应用程序连接PostgreSQL的简便方法?(嵌入PostgreSQL)

Handy way to connect PostgreSQL from an out-of-box application? (Embedding PostgreSQL)

本文关键字:PostgreSQL 方法 嵌入 连接 应用程序      更新时间:2023-10-16

我正在尝试在我的应用程序中使用PostgreSQL来管理一些记录。使用SQLite,不需要任何复杂的东西,因为它是一个文件数据库。

然而,对于PostgreSQL,即使我想连接localhost或本地套接字文件,也应该在使用它之前进行一些设置。当然,初始化只需要一次,但问题是,我不想因为这个系统设置问题而打扰我的应用程序的任何使用。我想让用户可以在开箱即用的状态下运行和使用我的应用程序。

我读过一篇关于在Arch Linux中使用PostgreSQL的wiki文章(https://wiki.archlinux.org/index.php/PostgreSQL),并且没有人愿意做这些事情来使用我的应用程序。此外,不可能从应用程序在wiki中运行这些命令,因为特定的设置取决于发行版,并且还需要root权限。

有没有办法连接PostgreSQL而不需要像SQLite那样复杂的初始化?或者,让用户的系统做好准备的简单方法?

仅供参考,我的应用程序是用C++和Qt编写的。而且,由于SQLite的局限性,我不能使用它。

如果你想要一个嵌入式数据库,PostgreSQL不是一个很好的选择。它是可用的,但与Firebird、SQLite等为嵌入而设计的数据库相比,它有点笨重。

绑定PostgreSQL

如果你想使用PostgreSQL,我建议将PostgreSQL二进制文件与你的程序捆绑在一起,并在使用你的程序时启动PostgreSQL服务器——假设你一次只需要一个程序实例。您可以从EDB获得方便的预构建的Pg二进制文件。您可以在启动时为用户提供一个选择-"使用现有的PostgreSQL"(在这种情况下,他们必须自己创建用户和数据库,进行任何pg_hba.conf更改等)或"启动私有PostgreSQL服务器"(当您使用捆绑的二进制文件运行自己的服务器时)。

如果他们想使用现有的数据库,您只需要告诉他们输入host/socket_directory、数据库名称、端口、用户名和密码。不要要求"密码",如果他们的hba配置不需要,它可能是空白的。

如果他们想使用一个私有实例,你可以启动一个-请参阅下面的指导。

不要捆绑PostgreSQL安装程序,并将其作为静默安装运行。这对可怜的用户来说是一场噩梦,他们不知道这个"postgresql"东西是从哪里来的,很可能会卸载它。或者,更糟糕的是,它会与他们自己的postgresql安装发生冲突,或者当他们稍后自己去安装postgresql时,发现他们已经有了它,甚至不知道密码。是 啊不要那样做。仅捆绑二进制文件,并自行控制您的私人PostgreSQL安装。

不要只使用系统上已有的postgres可执行文件来创建自己的私有实例。如果用户决定从9.2升级到9.3,那么您的私有实例将突然无法启动,并且您将无法访问旧的9.2二进制文件来执行pg_upgrade。如果您使用Pg的私有实例并将所需的二进制文件捆绑在程序中,则需要承担全部责任。

如何启动/控制Pg的私有实例

在第一次运行时,您运行PostgreSQL的initdb -D /path/to/datadir,指向程序的私有数据目录的一个空子目录。首先设置一些环境变量,这样就不会与系统上的任何普通PostgreSQL安装发生冲突。特别是,将PGPORT设置为某个随机的高ish端口,并将不同的unix_socket_directory配置参数指定为默认值。

一旦运行了initdb,您的程序可能需要修改postgresql.confpg_hba.conf以满足其需要。就我个人而言,我并不介意,我只是在PostgreSQL服务器启动命令行上传递我想要的任何参数作为覆盖,包括覆盖hba_file以指向我预先创建的一个。

如果数据目录在程序启动期间已经存在,则需要通过检查PG_VERSION文件来检查数据目录是否与当前PostgreSQL主版本匹配。如果没有,则需要复制datadir并运行pg_upgrade将其升级到捆绑的当前版本。为此,您需要为旧版本保留二进制文件的副本,因此您需要对更新过程进行特殊处理,或者将旧版本的二进制文件与新版本捆绑在更新安装程序中。

当您的程序启动时,在检查datadir是否已经存在并且是正确的版本后,将PGPORTenv var设置为与initdb相同的值,然后使用postgres -D /path/to/datadir和适当的日志文件输出参数等直接启动PostgreSQL。您启动的postmaster将您的程序作为父可执行文件,如果您的程序突然退出,将被终止。没关系,它会有时间清理,即使没有,PostgreSQL在设计上也是崩溃安全的。不过,您的程序仍然应该礼貌地要求PostgreSQL在退出之前通过发送适当的信号关闭。

您的应用程序现在可以使用libpq或其他方式连接到它拥有和控制的PostgreSQL实例,正常情况下,通过指定运行它的端口并(如果进行unix套接字连接)将host传递为/path/to/whatever/unix/socket/dir

与其直接控制postgres,您可以选择使用pg_ctl来驱动它。这样,当程序退出时,您可以让数据库保持运行状态,只有在发现它尚未运行时才启动它。如果用户在没有关闭PostgreSQL的情况下关闭系统,这并不重要——Pg通常会从操作系统中收到一些关闭警告,但不需要或不太关心它,它很乐意在下次启动时崩溃并恢复。

它肯定没有使用SQLite那么容易。在SQLite中,您只有一个包含整个数据库的文件,如果您"连接"到数据库,只需打开该文件。在PostgreSQL、MySQL、。。。您有一个数据库守护进程,它可以打开许多文件,数据库本身有多个文件,然后是事务日志、日志文件。。当然还有配置文件,它指定了所有这些文件的位置、资源使用、如何连接等等。数据库也需要定期维护以获得最佳性能,并且有很多可调整的内容。这一切都是因为所有这些数据库的通常用途是尽可能快地同时为多个客户端提供服务,而不是使设置变得简单。

仍然可以仅为单个用户设置PostgreSQL。要设置数据库,您需要创建一个数据库目录,在localhost上为TCP连接找到一个未使用的端口,或者更好地使用UNIX域套接字,用所需的参数(如使用的套接字、数据库目录、用户、资源限制、权限,以便同一机器上的其他用户无法连接)编写配置,启动数据库守护进程,初始化数据库(postgresql可以在同一个守护进程设置中为多个数据库提供服务),最后从程序连接到数据库。不要忘记定期运行维护任务,并以有序的方式关闭数据库。