0

我对 PostgreSQL 和 golang 都很陌生。主要是,我想了解以下内容:

  • 为什么我需要 Commit 语句来关闭连接,而其他两个Close调用却没有成功?
  • 还将感谢有关我使用游标的正确/错误方式的指针。

在下面的函数中,我gorp用来创建一个 CURSOR,逐行查询我的 Postgres DB 并将每一行写入一个 writer 函数:

func(txn *gorp.Transaction, 
     q string,
     params []interface{}, 
     myWriter func([]byte, error)) {

    cursor := "DECLARE GRABDATA NO SCROLL CURSOR FOR " + q
    _, err := txn.Exec(cursor, params...)
    if err != nil {
        myWriter(nil, err)
        return
    }

    rows, err := txn.Query("FETCH ALL in GRABDATA")
    if err != nil {
        myWriter(nil, err)
        return
    }

    defer func() {
        if _, err := txn.Exec("CLOSE GRABDATA"); err != nil {
            fmt.Println("Error while closing cursor:", err)
        }
        if err = rows.Close(); err != nil {
            fmt.Println("Error while closing rows:", err)
        } else {
            fmt.Println("\n\n\n Closed rows without error", "\n\n\n")
        }
        if err = txn.Commit(); err != nil {
            fmt.Println("Error on commit:", err)
        }
    }()

    pointers := make([]interface{}, len(cols))
    container := make([]sql.NullString, len(cols))
    values := make([]string, len(cols))
    for i := range pointers {
        pointers[i] = &container[i]
    }

    for rows.Next() {
        if err = rows.Scan(pointers...); err != nil {
            myWriter(nil, err)
            return
        }

        stringLine := strings.Join(values, ",") + "\n"
        myWriter([]byte(stringLine), nil)
    }
}

在该defer部分中,我最初只会Close使用rows,但后来我看到它pg_stat_activity保持打开idle in transaction状态,并带有FETCH ALL in GRABDATA查询。

打电话txn.Exec("CLOSE <cursor_name>")也没用。在那之后,我有一个CLOSE GRABDATA查询idle in transaction状态......

只有当我开始打电话Commit()时,连接才真正关闭。我想也许我需要调用 Commit 来执行交易中的任何事情,但如果是这样的话——我怎么会得到我的查询结果而不调用它呢?

4

1 回答 1

2

您想结束事务,而不是关闭已声明的游标。commit可以。 您可以在一个事务中运行多个查询- 这就是您无需提交即可看到结果的原因。

这些pg_stat_activity.state值是:active当您运行语句时(例如,begin transaction;fetch cursos),idle in transaction当您当前不运行语句时,但事务仍然开始,最后idle,在您运行end或之后commit,事务结束。在您断开会话结束并且根本没有任何行pg_stat_activity...

于 2018-02-19T20:54:43.727 回答