Pg connection busy: примеры (PHP)
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";
?>Соединение занято обработкой запроса... Соединение занято обработкой запроса... ... Соединение свободно.
Для работы с асинхронными запросами в 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 для асинхронной работы с 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())Запрос еще выполняется... Запрос еще выполняется... Запрос завершен.
В 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 8.1, параметр $connection ожидает объект типа PgSql\Connection вместо ресурса (resource). Передача старого типа ресурса вызывает устаревшее предупреждение (deprecated). В PHP 8.3 и 8.4 существенных изменений в работе функции не было.
Функция позволяет управлять пулом асинхронных запросов к разным соединениям.
<?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
$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";
}
?>Превышен таймаут выполнения запроса. Соединение освободилось.