Pg connection busy: примеры (PHP)

Проверка состояния асинхронного подключения: pg_connection_busy
Раздел: Базы данных (PostgreSQL)
pg_connection_busy(PgSql\Connection $connection): bool

Функция pg_connection_busy() в PHP определяет, занято ли асинхронное соединение с базой данных PostgreSQL выполнением запроса. Она применяется при работе с неблокирующими (асинхронными) подключениями для проверки статуса выполнения отправленного запроса.

Аргументы функции

Функция принимает один обязательный аргумент:

  • $connection (ресурс PgSql\Connection) - ресурс подключения к базе данных PostgreSQL, полученный с помощью pg_connect() и флага PGSQL_CONNECT_ASYNC или асинхронных функций.

Функция возвращает логическое значение: true, если соединение в данный момент обрабатывает запрос, и false, если оно свободно.

Примеры использования

Простая проверка статуса асинхронного подключения после отправки запроса.

<?php
$conn = pg_connect("host=localhost dbname=test user=postgres", PGSQL_CONNECT_ASYNC);

if (!$conn) {
    echo "Не удалось установить соединение.\n";
    exit;
}

// Отправляем асинхронный запрос
pg_send_query($conn, "SELECT pg_sleep(2);");

// Проверяем статус соединения
while (pg_connection_busy($conn)) {
    echo "Соединение занято обработкой запроса...\n";
    usleep(100000); // Ждем 0.1 секунды
}

echo "Соединение свободно.\n";
?>
Соединение занято обработкой запроса...
Соединение занято обработкой запроса...
...
Соединение свободно.
Похожие функции в PHP

Для работы с асинхронными запросами в PostgreSQL используется набор функций:

  • pg_send_query() и pg_send_query_params() - отправляют асинхронный запрос без ожидания результата.
  • pg_get_result() - получает результат асинхронного запроса. Эту функцию обычно вызывают после проверки pg_connection_busy().
  • pg_connection_status() - возвращает общий статус соединения (PGSQL_CONNECTION_OK, PGSQL_CONNECTION_BAD). Она проверяет состояние канала связи, а не занятость обработкой конкретного запроса.

Функция pg_connection_busy() уникальна для определения занятости соединения именно выполнением запроса в асинхронном режиме.

Аналоги в других языках
Python (библиотека asyncpg)

В Python для асинхронной работы с PostgreSQL используется библиотека asyncpg. Проверка занятости соединения неявно встроена в цикл событий.

import asyncio
import asyncpg

async def example():
    conn = await asyncpg.connect('postgresql://user:pass@localhost/db')
    # Запускаем длительный запрос
    task = asyncio.create_task(conn.fetchval('SELECT pg_sleep(2);'))
    # Проверяем, выполняется ли задача
    while not task.done():
        print("Запрос еще выполняется...")
        await asyncio.sleep(0.1)
    result = await task
    print("Запрос завершен.")
    await conn.close()

asyncio.run(example())
Запрос еще выполняется...
Запрос еще выполняется...
Запрос завершен.
JavaScript (Node.js, библиотека pg)

В Node.js с библиотекой 'pg' работа асинхронная по умолчанию через callback или Promise. Прямого аналога функции проверки занятости нет, так как запросы выполняются неблокирующе.

const { Client } = require('pg');
const client = new Client();

async function run() {
    await client.connect();
    // Отправляем запрос и ждем результата
    const res = await client.query('SELECT pg_sleep(2);');
    console.log('Запрос завершен.');
    await client.end();
}

run();
Запрос завершен.
Типичные ошибки

Передача некорректного ресурса соединения приводит к предупреждению и возврату false.

<?php
$result = pg_connection_busy('not_a_connection');
var_dump($result);
?>
Warning: pg_connection_busy() expects parameter 1 to be PgSql\Connection, string given in ...
bool(false)

Использование функции с синхронным соединением не имеет смысла, так как запросы блокируют выполнение скрипта до завершения. Функция может возвращать false даже во время выполнения запроса.

<?php
$conn = pg_connect("host=localhost dbname=test"); // Синхронное соединение
pg_query($conn, "SELECT pg_sleep(0.5);");
$busy = pg_connection_busy($conn);
var_dump($busy); // Скорее всего, false, так как запрос уже завершился
?>
bool(false)
Изменения в версиях PHP

Начиная с PHP 8.1, параметр $connection ожидает объект типа PgSql\Connection вместо ресурса (resource). Передача старого типа ресурса вызывает устаревшее предупреждение (deprecated). В PHP 8.3 и 8.4 существенных изменений в работе функции не было.

Расширенные примеры
Обработка нескольких асинхронных запросов

Функция позволяет управлять пулом асинхронных запросов к разным соединениям.

Пример php
<?php
$connections = [];
$queries = [
    "SELECT pg_sleep(3), 'Запрос 1';",
    "SELECT pg_sleep(1), 'Запрос 2';",
    "SELECT pg_sleep(2), 'Запрос 3';",
];

// Создаем несколько асинхронных соединений и отправляем запросы
foreach ($queries as $i => $sql) {
    $conn = pg_connect("host=localhost", PGSQL_CONNECT_ASYNC);
    $connections[$i] = $conn;
    pg_send_query($conn, $sql);
    echo "Запрос $i отправлен.\n";
}

// Ожидаем завершения всех запросов
$completed = 0;
while ($completed < count($connections)) {
    foreach ($connections as $i => $conn) {
        if ($conn && !pg_connection_busy($conn)) {
            $result = pg_get_result($conn);
            if ($result) {
                $row = pg_fetch_row($result);
                echo "Запрос $i завершен: {$row[1]}.\n";
                pg_free_result($result);
                $connections[$i] = null;
                $completed++;
            }
        }
    }
    usleep(100000);
}
?>
Запрос 0 отправлен.
Запрос 1 отправлен.
Запрос 2 отправлен.
Запрос 1 завершен: Запрос 2.
Запрос 2 завершен: Запрос 3.
Запрос 0 завершен: Запрос 1.
Имитация таймаута выполнения запроса
Пример php
<?php
$conn = pg_connect("host=localhost", PGSQL_CONNECT_ASYNC);
pg_send_query($conn, "SELECT pg_sleep(10);"); // Долгий запрос

$timeout = 3; // секунды
$start = time();

while (pg_connection_busy($conn)) {
    if (time() - $start > $timeout) {
        echo "Превышен таймаут выполнения запроса.\n";
        pg_cancel_query($conn); // Попытка отменить запрос
        break;
    }
    usleep(200000);
}

if (!pg_connection_busy($conn)) {
    echo "Соединение освободилось.\n";
}
?>
Превышен таймаут выполнения запроса.
Соединение освободилось.

PHP pg_connection_busy function comments

En
Pg connection busy Get connection is busy or not