我仍然不是golang 的专家,还在学习.这也是我第一次使用PostgreSQL

import "github.com/jackc/pgx/v5/pgxpool"

const DB = "postgres://postgres:xxx@localhost:5432/mydb?pool_min_conns=1&pool_max_conns=5&pool_max_conn_idle_time=30s"

dbpool, err := pgxpool.New(context.Background(), DB)
if err != nil {
    log.Fatal("Unable to create connection pool: "+err.Error())
}
defer dbpool.Close()

1. How to get a connection from the pool and use prepared statements, where you pass the SQL and the SQL values as two separate arguments?

来自PHP,以前从未使用过数据库池.

2. How to ensure when you pull a connection from the pool is "fresh" and you don't continue on a previous not completed transaction (rollback/commit)?

3. The same when you release a connection back to the pool. Will it automatically do a rollback if the context is cancelled or the request failed?

4. How make use of goroutines when requesting the database? Is it possible to make parallel select queries in the same transaction or does all queries have to be serial? I guess all write queries have to be serial?

推荐答案

  1. 如何从池中获取连接并使用预准备语句,将SQL和SQL值作为两个单独的参数传递?

通常不需要.池负责管理连接(获取和释放)以及管理准备好的语句(创建和缓存).

但是,如果您希望保持控制,则可以使用Acquire方法或其任何相关方法显式地从池中获取连接.

同样,如果您想要手动创建和重用预准备语句(例如,您需要在紧密循环中执行相同的查询,但您不想依赖池对预准备语句的缓存),则可以使用获取的Connection的Conn方法,该方法返回连接的*pgx.Conn表示形式,该方法有一个名为Prepare的方法.

  1. 如何确保当您从池中拉出连接时是"新的",并且您不会继续处理先前未完成的事务(回滚/提交)?

池的获取方法返回available个连接.根据定义,正在使用的连接(即未释放的连接)是不可用的,Acquire方法不会返回这些连接.

  1. 当您释放回池的连接时也是如此.如果上下文被取消或请求失败,它是否会自动回滚?

释放回池的连接所持有的资源(如果不是空闲的话)将是destroyed.关于事务提交/回滚,都不会自动调用,documentation明确表示:"Commit or Rollback must be called on the returned transaction to finalize the transaction block."

  1. 在请求数据库时如何使用Goroutines?是否可以在同一事务中进行并行SELECT查询,或者所有查询都必须是连续的吗?我猜所有的写入查询都必须是连续的?

池子可以安全地同时使用.然而,同时使用pgxpool.Connpgxpool.Tx都不安全.


Example:

Begin不支持自动回滚或自动提交,如documentation所述,您自己必须调用RollbackCommit来"完成事务块".

func f(ctx context.Context, pool *pgxpool.Pool) (err error) {
    tx, err := pool.Begin(ctx)
    if err != nil {
        return err
    }
    defer func() {
        if err != nil {
            tx.Rollback(ctx)
        } else {
            tx.Commit(ctx)
        }
    }()

    _, err := tx.Exec(ctx, "insert into users (email) values ($1)", "c@em.com")
    if err != nil {
        return err
    }

    var id int
    row := tx.QueryRow(ctx, "select id from users where email = $1", "c@em.com")
    if err := row.Scan(&id); err != nil {
        return err
    }

    // NOTE: the above is just an example, if you need the auto
    // generated id of an inserted record, please use the RETURNING
    // clause supported by PostgreSQL.
    return nil
}

然而,如果您希望PGx为您的交易使用RollbackCommit,您可以使用BeginFunc.

func f(ctx context.Context, pool *pgxpool.Pool) (err error) {
    return pool.BeginFunc(ctx, func(tx pgx.Tx) error {
        _, err := tx.Exec(ctx, "insert into users (email) values ($1)", "c@em.com")
        if err != nil {
            return err
        }

        var id int
        row := tx.QueryRow(ctx, "select id from users where email = $1", "c@em.com")
        if err := row.Scan(&id); err != nil {
            return err
        }

        // NOTE: the above is just an example, if you need the auto
        // generated id of an inserted record, please use the RETURNING
        // clause supported by PostgreSQL.
        return nil
    })
}

Postgresql相关问答推荐

将几个左连接合并为一个

"错误:无法创建用户:错误:关系\users\违反了非空约束

右连接 postgresql 出现语法错误

如何在 postgres where 子句中使用 or 对条件进行组合或分组

求和直到达到一个值 postgresql

无法使用golang在postgresql中使用自定义类型插入/更新数据

gorm 创建并返回值 many2many

如何在typeorm和嵌套js中将运行时变量设置为postgresql

PostgreSQL SELECT 结果具有不同的 id,它更喜欢来自另一个表的特定值

如何在 postgresql 上使用 sqlalchemy 进行正确的 upsert?

PostgreSQL:是否可以将枚举转换为整数?

运算符不存在:integer = integer[] 在使用 ANY 的查询中

如何从 postgresql Select 查询中的 age() 函数中仅获取年份

将 PostgreSQL 配置为仅适用于 LOCALHOST 或指定的 ip + 端口

在函数中返回字段作为插入结果

使用 pg_dump 和 psql -U postgres db_name < ... 移动数据库会导致ERROR: relation "table_name" does not exist

Django 1.9.2 AssertionError:database connection isn't set to UTC

将数据从 MS SQL 迁移到 PostgreSQL?

PostgreSQL 中的行编号

错误:表tablename上的更新或删除违反外键约束