Драйвер pq: подготовленный оператор не существует

Я пытаюсь подключиться к базе данных postresql с драйвером pq в Go. Когда я делаю это на локальной копии базы данных, со строкой подключения, как

DB, err = sql.Open("postgres", "user=user password=pwd dbname=mydb sslmode=disable")

все работает хорошо

Однако, когда я переключаюсь на рабочий сервер, где соединение проходит через pgbouncer:

DB, err = sql.Open("postgres", "user=user password=pwd host=/var/run/pgbouncer port=port dbname=mydb sslmode=disable")

Я продолжаю получать одну и ту же ошибку для всех запросов, однако простую:

Database error: pq: S:"ERROR" M:"prepared statement \"1\" does not exist" C:"26000" F:"prepare.c" L:"519" R:"FetchPreparedStatement"

(это всегда "подготовленное утверждение \"1\"", независимо от запроса, который я пытаюсь передать)

Запрос в обоих случаях выполняется просто следующим образом:

res_rows, err := DB.Query(query)
if err != nil {
    log.Printf("Database error: %s\n", err)
}
for res_rows.Next() {
    ...
}

Googling предлагает отключить готовые заявления, но я не знаю, как это сделать в Go, и я не уверен, что это вообще поддерживается. Любая помощь (даже предложение использовать что-то еще полностью) будет принята с благодарностью.

4 ответа

Решение

Пакет драйвера

type Queryer

type Queryer interface {
    Query(query string, args []Value) (Rows, error)
}

Queryer это необязательный интерфейс, который может быть реализован Conn,

Если Conn не реализует Queryer, sql пакет-х DB.Query сначала подготовит запрос, выполнит оператор, а затем закроет оператор.

Я не вижу, где реализует драйвер lib / pq PostgreSQL Queryer, Следовательно DB.Query запрос подготовлен перед выполнением.

PgBouncer не поддерживает функцию PREPARE для всех методов объединения: матрица функций для режимов объединения.

Если вы используете PgBouncer, вам нужно установить binary_parameters=yes к вашей базе данных подключение dsn в качестве параметра запроса

попробуй это:
DB, err = sql.Open("postgres", "user=user password=pwd dbname=mydb sslmode=disable, binary_parameters=yes")

Драйвер Postgres теперь имеет решение для устранения этой проблемы: https://github.com/lib/pq/issues/389

Его нет в документации, но он работает как положено, в том числе с включенными PgBouncer и пулами транзакций.

Начиная с версии PgBouncer 1.21.0, он теперь поддерживает именованные операторы уровня протокола, что почти наверняка устранит эту ошибку. Вы можете включить эту поддержку, установивmax_prepared_statementsна ненулевое значение в файле конфигурации PgBouncer. Подробную информацию можно найти в документации: https://www.pgbouncer.org/config.html#max_prepared_statements .

Другие вопросы по тегам