当前位置: 首页 > 面试题库 >

如何在Go中将单个Postgres DB连接重用于行插入?

巫健柏
2023-03-14
问题内容

我正在尝试使用Go连接到DB的单个连接,该连接将数据从Rabbitmq接收到的每条新消息插入Postgres表中的一行数据,该连接在下面的代码的init函数中打开。

该代码不只是打开一个连接,而是打开497并最大化,这导致行插入停止。

我已经使用这些问题的信息试图打开和关闭在Go应用程序的数据库连接,并在函数内部开放式数据库连接该说我应该打开一个连接,并使用全球数据库,以便主要功能的SQL语句传递到在打开连接初始化函数。

我以为我已经做到了,但是每行新连接都会打开,因此一旦达到postgres连接限制,代码就会停止工作。

我是Go语言的新手,并且编程经验有限,在过去的两天里,我一直在尝试了解/解决此问题,我确实可以通过一些帮助来了解我在哪里出错了…

var db *sql.DB

func init() {
    var err error
    db, err = sql.Open ( "postgres", "postgres://postgres:postgres@SERVER/PORT/DB")
    if err != nil {
        log.Fatal("Invalid DB config:", err)
    }
    if err = db.Ping(); err != nil {
        log.Fatal("DB unreachable:", err)
    }
}

func main() {

// RABBITMQ CONNECTION CODE IS HERE

// EACH MESSAGE RECEIVED IS SPLIT TO LEGEND, STATUS, TIMESTAMP VARIABLES

// VARIABLES ARE PASSED TO sqlSatement

        sqlStatement := `
        INSERT INTO heartbeat ("Legend", "Status", "TimeStamp")
        VALUES ($1, $2, $3)
`
        // sqlStatement IS THEN PASSED TO db.QueryRow

        db.QueryRow(sqlStatement, Legend, Status, TimeStamp)
    }
}()

<-forever
}

完整代码如下所示:

package main

import (
    "database/sql"
    "log"
    _ "github.com/lib/pq"

    "github.com/streadway/amqp"
    "strings"
)
var db *sql.DB

func failOnError(err error, msg string) {
    if err != nil {
        log.Fatalf("%s: %s", msg, err)
    }
}

func init() {
    var err error
    db, err = sql.Open ( "postgres", "postgres://postgres:postgres@192.168.1.69:5432/test?sslmode=disable")
    if err != nil {
        log.Fatal("Invalid DB config:", err)
    }
    if err = db.Ping(); err != nil {
        log.Fatal("DB unreachable:", err)
    }
}

func main() {
    conn, err := amqp.Dial("amqp://Admin:Admin@192.168.1.69:50003/")
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()

    q, err := ch.QueueDeclare(
        "HEARTBEAT", // name
        false,       // durable
        false,       // delete when unused
        false,       // exclusive
        false,       // no-wait
        nil,         // arguments
    )
    failOnError(err, "Failed to declare a queue")

    msgs, err := ch.Consume(
        q.Name, // queue
        "",     // consumer
        false,  // auto-ack
        false,  // exclusive
        false,  // no-local
        false,  // no-wait
        nil,    // args
    )
    failOnError(err, "Failed to register a consumer")

    forever := make(chan bool)

    go func() {

        for d := range msgs {
            myString := string(d.Body[:])
            result := strings.Split(myString, ",")
            Legend := result[0]
            Status := result[1]
            TimeStamp := result[2]

            sqlStatement := `
    INSERT INTO heartbeat ("Legend", "Status", "TimeStamp")
    VALUES ($1, $2, $3)
    `
            //
            db.QueryRow(sqlStatement, Legend, Status, TimeStamp)
        }
    }()

    <-forever
}

问题答案:

首先,*sql.DB不是连接而是连接池,它将打开所需数量的连接以及postgres服务器允许的数量。仅当池中没有空闲的可用连接时,它才会打开新连接。

因此,问题在于数据库打开的连接没有被释放,为什么?因为您使用时QueryRow未调用Scan返回*Row值。

引擎盖下*Row有一个*Rows实例,该实例可以访问其自己的连接,并且该连接在Scan被调用时会自动释放。如果Scan未调用,则连接不会释放,这会导致DB池在下一次调用时打开新连接QueryRow。因此,由于您不释放任何连接,因此请DB继续打开新的连接,直到达到postgres设置所指定的限制,然后下一次调用QueryRow挂起,因为它等待连接变为空闲状态。

因此,Exec如果您不关心输出,则需要使用,或者需要调用Scanreturn *Row



 类似资料:
  • 问题内容: 我收集到有两种方法可以在Windows中(在Windows上)连接到Oracle DB: github.com/tgulacsi/goracle github.com/mattn/go-oci8 但是对于我这个级别的人(开源+ golang的初学者)来说,这两种方法/驱动程序非常棘手。 在不同的机器上进行部署,开发等工作时,这也是一个负担(也假设它会工作)。 有没有更好的方法可以在go

  • JPA中有没有一种方法可以将行直接插入到连接表中?我有以下合同和附件实体: < code >附件实体: 由于线程并发问题,我想直接向合约添加附件,而无需加载合约,将附件添加到列表中并保留/保存合约,因为 Contract 对象本身中没有正在更新的数据。为了更详细一些,我有多个线程并行保存附件,如果我要在所有这些线程中持久化合约,我需要加入某种并发控制以避免乐观锁定异常。鉴于 Contract 实体

  • 我正在制作一个实时多人游戏socket.io和node.js,我有一个html文件,运行一个公共脚本连接到服务器并运行命令,以及定义我需要的库

  • 问题内容: 我将mongodb的node-mongodb-native驱动程序用于编写网站。 我有一个关于如何一次打开mongodb连接,然后在中的集合名称用户和中的集合名称帖子中使用它的问题 我想在其中打开数据库连接以为用户插入/保存数据并发布帖子 当前代码,我的 我曾经在如下 和 问题答案: 您可以连接一次,然后根据需要重复使用多次: 然后重用它:

  • 我正在尝试组合切片和切片。我怎么能在围棋中做到这一点? 我试过: 但是得到: 然而,文档似乎表明这是可能的,我遗漏了什么?