交易,提交,回滚和使用PostgreSQL的文件
#postgres #c #vely #acid

在交易中写文件并插入数据

虽然常规操作系统文件不是数据库系统的一部分,但您可以提交数据库事务并编写文件,以便在提交数据库记录的情况下确保文件编写。请注意,这与文件是交易的一部分不同 - 您必须将数据库的设施使用;但是,这实际上是将文件与数据库记录联系起来的一种方法。例如,您可能是编写文件并将其信息插入数据库。在此示例中,您将使用PostgreSQL进行此操作,但是通常您可以使用其他支持交易的数据库 - 详细介绍下一步。

Postgresql

PostgreSQL(或Just Postgres)是一个流行的开源数据库,它使用SQL来创建和操纵数据,并且也符合酸性。这意味着原子能,一致性,隔离和耐用性,这是数据库应遵守的属性可靠地处理交易。这非常重要,因为没有它,几乎任何业务中使用的数据可能会丢失,重复或完全错误。想象一下,如果银行没有正确实施交易 - 您的支票存款或帐户之间的简单转移可能不会像您期望的那样通过。

那么酸到底是什么意思?

  • 原子能意味着交易中的一切都成功或无能为力。因此,如果在交易期间,其中某些部分已经完成,而其他部分则不完整,并且交易中断(例如,通过系统崩溃),则部分完成的项目将被卷回到它们处的位置交易。因此,您将看到SQL命令,例如开始和提交表示交易的开始和结束的sql命令,而回滚用来取消交易。
  • 一致性意味着数据将符合诸如唯一性,预定关系(例如外键),数据范围约束等规则,换句话说,如果交易即将违反为数据库建立的任何规则,然后,它必须回滚,并且数据不能与数据库规则相反。
  • 隔离意味着每次交易就像一个岛上本身,并且不能受到任何其他并发交易中发生的任何变化的影响。这并不意味着交易不能以同样的方式进行;只要他们不会彼此影响,他们就可以。因此,这些交易将以相同的数据运行的方式,这意味着它们可能会产生不良或不一致的结果。不同的数据库采用不同的方法来确保这一点。
  • 耐用性意味着一旦数据库通知您,它已经完成了交易,甚至在紧随其后的系统崩溃都不会消除其效果。 当您使用交易时,PostgreSQL可以保证这些质量。其他数据库(例如带有InnoDB发动机的SQLite或MariadB)也符合酸含量。在大多数情况下,您可以编写与所有这些数据库一起使用的相同的SQL语句,并且可以以相同的方式使用交易。 ##连接到数据库 与PostgreSQL一起使用本机C库是最快的。在这里,我将使用使用此类库的Vely。它还可以使连接保持活力,从而避免在连接/断开连接周期上浪费时间。此外,您可以使用已准备好的SQL语句,在该语句中,服务器将在将来使用SQL语句进行一次解析,然后在将来使用解析的语句树,而无需再次进行。持续的连接和解析语句齐头并进,因为解析语句仅在一个会话中有效。因此,如果您使用不持续的连接方法,那么您将很少有准备好的陈述。如果丢失了连接,则Vely将自动重新建立该连接 - 例如,如果重新启动PostgreSQL Server,可能会发生。 ##先决条件 首先,install Postgres。另外,install Vely将用于为此示例创建本机可执行文件 - Vely是C编程语言的框架。 ##设置数据库 登录为“ PSQL”实用程序并执行:
echo "create user $(whoami);
create database db_items with owner=$(whoami);
grant all on database db_items to $(whoami);
\q
" | sudo -u postgres psql

在这里,您将创建数据库“ db_items”和用OS Linux用户命名的用户,创建无密码的Postgres用户。原因是因为它为您提供了更好,更轻松的安全性 - 只有您作为当前的操作系统用户登录,可以访问数据库,因此您不需要密码。然后,您将为数据库用户提供基本数据库“ db_items”的权限,并能够创建对象,数据等。

最后,在此数据库中创建表“ item_list”:

echo "create table item_list (item_id bigserial primary key, item_name varchar(30), item_desc varchar(100))" | psql -d db_items

这将创建表“ item_list”,其中包含项目名称和描述,以及自动生成的主键作为ID。

访问数据库

为了访问数据库,您将需要一个database_config_file。该文件指定数据库用户名和密码以及任何其他连接字符串参数。请咨询Postgres文档以查看所有可用参数。在这里,创建名为“项目”的数据库配置文件。您可以调用此文件的任何内容,但是它的名称在代码中用于引用数据库,因此,如果更改它,则也将其更改为以下代码。使用此bash代码创建文件“项目”:

echo "user=$(whoami) dbname=db_items"  > items

这实际上是本机PostgreSQL客户端配置文件,因此学习其格式也可以帮助您在其他地方。您将指定Postgres用户名(这是您的OS用户名称或$(Whoami)bash表达式的结果),并且数据库名称为“ db_items” - 同样,这就是我们已经创建的数据库。没有密码,因为登录是无密码的,如上所述。

代码

创建文件“ add_item.vely”并将其复制到它(请注意,该文件的名称始终匹配其中实现的函数名称):


#include "vely.h"

void add_item() {
    out-header default

    input-param name
    input-param desc

    // Start transaction
    begin-transaction @items
    // Insert data
    run-query @items = "insert into item_list (item_name, item_desc) values ('%s', '%s') returning (item_id)" \
            output define item_id : name, desc  \
            error define err_code error-text define err_text affected-rows define rows
        // Check if no error and a row is actually inserted
        if (!strcmp (err_code, "0") && rows == 1) {
            // Construct file name
            write-string define item_file
            @item_added_<<p-out item_id>>
            end-write-string
            // Write file
            write-file item_file from item_id status define write_st
            if (write_st < 0) {
                // Could not write file, even if insert okay
                rollback-transaction @items
                @Could not write to file, status <<p-num write_st>>
            } else {
                // Both write file and insert okay
                commit-transaction @items
                @SUCCESS, item added to database and written to a file (<<p-out item_file>>)
            }
        } else {
            // Could not insert
            rollback-transaction @items
            @Could not insert to database, error <<p-out err_text>>, error code <<p-out err_code>>
        }
    end-query
}

此代码是一个请求处理程序 - 它处理请求,例如HTTP(S)请求或命令行中的请求。这是其工作方式:

  • 首先,您将插入数据库的数据作为输入参数。请注意,在您获得“名称”和“ desc”变量的开头的input-param - 这些将来自程序的呼叫者。无论您是从网络(即浏览器)还是从命令行调用您的程序。
  • 接下来,用“ @Items”指定的数据库开始事务(begin-transaction)。同样,“项目”是您创建的数据库配置文件,描述了数据库。
  • 使用run-query插入数据:使用“%s”指定查询作为结肠后的参数的占位符(“:”)。输出是创建的一行的唯一ID(在“输出”子句中,并使用“ Define”子等级创建),也是任何错误信息以及插入的行数(在“错误”,“错误text”和“受影响的行)中 - 级别的“条款分别)。所有这些信息以后很有用,在错误检查或功能上处于错误检查中。
  • 由于获得了错误代码和错误文本,因此您将检查错误并确保实际插入了行。如果没有,请回滚交易并完成。
  • 如果数据插入还可以,请写一个文件。此文件的名称基于此ID,其内容是相同的,但是文件的名称和内容都取决于您 - 这仅是出于演示目的。使用write-string创建文件名,而write-file将数据写入文件。
  • 如果写入文件成功,commit-transaction。如果失败,请用rollback-transaction卷回去。
  • 少数机会可能会失败,在这种情况下,文件将保留。这通常不是问题,因为它是数据库中始终首先查找的记录,即,没有书面文件,您将没有记录 - 因此,代码中不包含错误处理。 您还可以使用上述代码中的“ run-pregred-Query”语句而不是“ run-Query”使用准备的SQL语句。

和“@” output_statement将数据发送到标准输出,如果这是命令行程序,则可以是实际的“ stdout”流,如果这是Web应用程序,则可以是浏览器。好的事情是,这对两者都相同。 p-out语句输出一个字符串,当将其放置在<<和>>之间时,它被“嵌入”到输出语句中。

创建并制作应用程序

当您开始使用Vely应用程序时,必须先使用vf程序经理来创建它:

sudo vf -i -u $(whoami) items_app

“ - i”选项说要创建一个应用程序。 “ -u”选项说哪个用户将拥有它,在这种情况下为“ $(whoami)”,它是“当前登录用户”的linix说话。最后,应用程序名称为“ item_app”。

要制作您的应用程序,请使用vv工具:

vv -q --db='postgres:items'

这将收集当前目录中的所有.Vely文件(在这种情况下只有一个),将所有Vely语句(如run-Query)处理到C代码中,然后将其编译并将其链接到本机应用程序中。注意“ -db ='Postgres:items'”选项 - 它指出您的程序使用名为“项目”的数据库,并且数据库供应商为PostgreSQL。您可以拥有任意数量的数据库和任何数量的受支持供应商。

将在“/var/lib/vv/bld/ittem_app”目录中产生两个可执行文件。请注意“ tooke_app”子目录 - 它与上面创建的应用程序名称匹配。该目录就像用于您的应用程序的划痕,这是所有生成的代码所处的位置。创建的一个可执行文件将是可以从命令行运行的“ tock_app”。另一个是“ tooke_app.fcgi”,您可以作为FastCGI应用程序服务器(是Web应用程序)运行。

从指令行跑

执行您的程序 - 请参阅下文有关:

export REQUEST_METHOD=GET
export QUERY_STRING="name=Wifi+Camera&desc=Feature+rich+wifi+camera+for+the+home"
export SCRIPT_NAME="/items_app"
export PATH_INFO="/add_item"
export VV_SILENT_HEADER="yes"
/var/lib/vv/bld/items_app/items_app

您可能会得到:

SUCCESS, item added to database and written to a file (item_added_1)

验证数据已添加:

echo "select * from item_list" | psql -d db_items

结果是:

 item_id |  item_name  |               item_desc
---------+-------------+---------------------------------------
       1 | Wifi Camera | Feature rich wifi camera for the home
(1 row)

您的请求已将数据添加到数据库!

Vely都是关于标准HTTP请求的。因此,即使您运行命令行程序,也可以通过接收HTTP请求来实现。这就是为什么有一个请求方法(“ get”),一个脚本名称(这是通往应用程序名称的途径“ items_app”),一个路径信息(这是请求处理程序“ add_item”的途径,即您的代码上面的代码)和一个包含输入数据(“名称”和“ desc”)的查询字符串,该字符串与代码中的输入参数匹配。

这使得为命令行执行和Web执行构建程序非常容易,因为它们是相同的。您无需编写两个代码库,只需调试一次。另外,您几乎可以在Web上可以在命令行上执行任何操作,因此您可以编写程序,而无需设置Web服务器。

注意VV_SILENT_HEADER环境变量 - 它抑制HTTP标头输出。如果不存在,您将获得HTTP标头,与浏览器相同。

您当然可以通过启动自己的应用程序服务器来作为Web服务运行此示例 - 请参阅this as an example

图像版权(c)Sergio Mijatovic 2023
本文根据CC-BY-4.0获得许可,该文章允许在商业上复制和重新分配 - 有关更多详细信息,请参见许可。