douqiu9529 2018-02-19 19:21
浏览 288
已采纳

执行后事务保持在pg_stat_activity状态

I'm quite new to both PostgreSQL and golang. Mainly, I am trying to understand the following:

  • Why did I need the Commit statement to close the connection and the other two Close calls didn't do the trick?
  • Would also appreciate pointers regarding the right/wrong way in which I'm going about working with cursors.

In the following function, I'm using gorp to make a CURSOR, query my Postgres DB row by row and write each row to a writer function:

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("


 Closed rows without error", "


")
        }
        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, ",") + "
"
        myWriter([]byte(stringLine), nil)
    }
}

In the defer section, I would initially, only Close the rows, but then I saw that pg_stat_activity stay open in idle in transaction state, with the FETCH ALL in GRABDATA query.

Calling txn.Exec("CLOSE <cursor_name>") didn't help. After that, I had a CLOSE GRABDATA query in idle in transaction state...

Only when I started calling Commit() did the connection actually close. I thought that maybe I need to call Commit to execute anything on the transation, but if that's the case - how come I got the result of my queries without calling it?

  • 写回答

1条回答 默认 最新

  • doufu6130 2018-02-19 20:54
    关注

    you want to end transaction, not close a declared cursor. commit does it. you can run multiple queries in one transaction - this is why you see the result without committing.

    the pg_stat_activity.state values are: active when you run the statement (eg, begin transaction; or fetch cursos), idle in transaction when you don't currently run statements, but the transaction remains begun and lastly idle, after you run end or commit, so the transaction is over. After you disconnect the session ends and there's no row in pg_stat_activity at all...

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 VB.NET2022如何生成发布成exe文件
  • ¥30 matlab appdesigner私有函数嵌套整合
  • ¥15 给我一个openharmony跑通webrtc实现视频会议的简单demo项目,sdk为12
  • ¥15 vb6.0使用jmail接收smtp邮件并另存附件到D盘
  • ¥30 vb net 使用 sendMessage 如何输入鼠标坐标
  • ¥15 关于freesurfer使用freeview可视化的问题
  • ¥100 谁能在荣耀自带系统MagicOS版本下,隐藏手机桌面图标?
  • ¥15 求SC-LIWC词典!
  • ¥20 有关esp8266连接阿里云
  • ¥15 C# 调用Bartender打印机打印