当前位置: 首页 > 知识库问答 >
问题:

无法使用线程将数据插入到带有DBIish的PostgreSQL中。出什么问题了?

姜宏放
2023-03-14

编辑:莫里茨解决了这个问题。我在代码的行中添加了一个错误的注释。

我的应用程序是一个与游戏客户端对话的网络服务器。服务器是多线程的,Postgres允许。当将客户端数据加载到数据库中时,我注意到并行请求失败,出现了几个不同的错误,这些错误对我来说都没有意义。

这个简短的测试用例将嵌套哈希转储到数据库中。当在没有start的情况下运行时,它可以完美地工作。当使用线程运行时,它几乎总是给出以下一个或多个错误:

DBDish::Pg:错误:(7)在方法准备在D:\rakudo\share\perl6\site\Source\BAD7C1548F63C7AA7BC86BEDDA0F7BD185E141AD(DBDish::Pg::Connection)第48行在testcase. p6的块中第62行
在testcase. p6的子add-enum-mappings中第59行在testcase. p6第91行

DBDish::Pg:Error:Error:prepared语句“Pg_3448_16”已存在于testcase块中的方法prepare的D:\rakudo\share\perl6\site\sources\BAD7C1548F63C7AA7BC86BEDDA0F7BD185E141AD(DBDish::Pg::Connection)第46行。p6第62行
在测试用例中添加枚举映射。p6测试用例块中的第59行。p6第91行

DBDish::Pg:错误:方法执行的参数数错误:在D:\rakudo\share\perl6\site\Source\65FFB78EFA30486D1C4D339882A410E3C94AD2(DBDish::StatementHandle)行40中的方法执行得到1,预期0(-1)####################################################################################################################################################################################

消息类型0x31从服务器到达,而空闲消息类型0x5a从服务器到达,而空闲消息类型0x74从服务器到达,而空闲消息类型0x6e从服务器到达,而空闲消息类型0x5a在空闲时从服务器到达

这是密码。(如果选择运行它,请记住设置正确的密码。它创建/操作名为“enummappings”的表,但不执行其他操作。)肉在add-enum-mappings()中。其他一切都只是设置。哦,并且dbh()为每个线程创建一个单独的DB连接。根据PostgreSQL文档,这是必要的。

#!/usr/bin/env perl6

use DBIish;
use Log::Async;

my Lock $db-lock;
my Lock $deletion-lock;
my Lock $insertion-lock;

INIT {
    logger.send-to($*ERR);
    $db-lock .= new;
    $deletion-lock .= new;
    $insertion-lock .= new;
}

# Get a per-thread database connection.
sub dbh() {
    state %connections;
    my $dbh := %connections<$*THREAD.id>; # THIS IS WRONG. Should be %connections{$*THREAD.id}.
    $db-lock.protect: {
        if !$dbh.defined {
            $dbh = DBIish.connect('Pg', :host<127.0.0.1>, :port(5432), :database<postgres>,
                :user<postgres>, :password<PASSWORD>);
        }
    };

    return $dbh;
}

sub create-table() {
    my $name = 'enummappings';
    my $column-spec =
        'enumname TEXT NOT NULL, name TEXT NOT NULL, value INTEGER NOT NULL, UNIQUE(enumname, name)';
    my $version = 1;
    my $sth = dbh.prepare("CREATE TABLE IF NOT EXISTS $name ($column-spec);");
    $sth.execute;

    # And add the version number to a version table:
    dbh.execute:
        "CREATE TABLE IF NOT EXISTS tableversions (name TEXT NOT NULL UNIQUE, version INTEGER NOT NULL);";
    $sth = dbh.prepare:
        'INSERT INTO tableversions (name, version) VALUES (?, ?)
            ON CONFLICT (name)
                DO
                    UPDATE SET version = ?;';
    $sth.execute($name, $version, $version);
}

sub add-enum-mappings($enumname, @names, @values --> Hash) {
    $deletion-lock.protect: {
        my $sth = dbh.prepare('DELETE FROM enummappings WHERE enumname = ?;');
        $sth.execute($enumname);
    };

    my @rows = (^@names).map: -> $i {$enumname, @names[$i], @values[$i]};
    info "Inserting @rows.elems() rows...";
    $insertion-lock.protect: {
        my $sth = dbh.prepare('INSERT INTO enummappings (enumname,name,value) VALUES '~
            ('(?,?,?)' xx @rows.elems).join(',') ~ ';');
        $sth.execute(@rows>>.list.flat);
    };

    return %(status => 'okay');
}

# Create a bunch of long enums with random names, keys, and values.
sub create-enums(--> Hash[Hash]) {
    my @letters = ('a'..'z', 'A'..'Z').flat;
    my Hash %enums = ();
    for ^36 {
        my $key = @letters.pick(10).join;
        for ^45 {
            my $sub-key = @letters.pick(24).join;
            %enums{$key}{$sub-key} = (0..10).pick;
        }
    }
    return %enums;
}

sub MAIN() {
    create-table;

    await do for create-enums.kv -> $enum-name, %enum {
        start {
            add-enum-mappings($enum-name, %enum.keys, %enum.values);
            CATCH { default { note "Got error adding enum: " ~ .gist; } }
        };
    }
}

我在视窗10上,有一台8核电脑。我知道我可以单线程插入数据,但是如果游戏一次获得一百个连接呢?我需要永远解决这个问题。

共有1个答案

陶博赡
2023-03-14

我怀疑你的问题在这里:

my $dbh := %connections<$*THREAD.id>;

%散列

错误发生后,您只有一个在所有线程之间共享的DB连接,我想这就是DBIish(或底层postgresql C客户端库)不满意的地方。

 类似资料:
  • 我正在使用Spring Boot 2和Liquibase(核心3.6.2),我的DB是PostgreSQL。我在db.changelog-master.xml中通过这个变更集创建表: 用于从csv文件向该表插入值的下一个变更集: 如果我在列id中指定类型UUID而不是字符串,liquibase将告诉我: 测试内容。csv文件: 当我运行应用程序时,liquibase创建了表,当它尝试插入值时,我收

  • 我正在尝试使用jdbc将数据插入另一个表中的一个表,该表的snowflake中有自动递增列。我跳过了auto increment列,并从下面的查询中只插入了必需的列 它以正确的自动递增顺序正确插入数据,但如果我插入另一个值,自动递增值的值会随机递增 它反映了这个问题, 本期共有260张唱片。这是自动递增键的问题,请帮助。谢谢 另外,如果col1不是主键,并且在snowflake控制台上执行查询,也

  • 我是mysql和php的初学者。在这个问题上陷入了困境。不知道问题出在哪里。但是如果我直接执行insert查询,它就会被执行,而如果我从用户那里接受它,它就不会被执行(代码中显示了这一点)。可能问题出在我用来检索用户提交的值的$\u POST[]方法上。我已经提交了两个代码,addbooks。php(用户提交值的表单)和add。php(插入数据库)。

  • 我正在用php制作一个爬虫程序,这个爬虫程序正在工作 但我在将标题添加到数据库时遇到一些问题,这是错误: 致命错误:未捕获PDOException:SQLSTATE[42S22]:未找到列:C:\xampp\htdocs\webcrawler\php web crawler\index.php:29堆栈跟踪:#0 C:\xampp\htdocs\webcrawler\php web crawler

  • 问题内容: 我希望能够将bigints数组写入要用于Go历史记录的表中。不幸的是,我不能,当我这样做时`sql: converting Exec argument 这是我要插入的表的结构: 问题答案: 使用自定义类型实现database / sql / driver.Valuer:

  • 事情是这样的 我不知道发生了什么,如果有人能帮忙,我会非常感激的。THX!