Pg transaction status: примеры (PHP)

Использование pg_transaction_status для контроля состояния транзакций
Раздел: Базы данных (PostgreSQL)
pg_transaction_status(PgSql\Connection $connection): int
Описание функции pg_transaction_status

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

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

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

  • $connection (ресурс подключения PostgreSQL) - Соединение к базе данных PostgreSQL, полученное через pg_connect() или pg_pconnect().

Функция возвращает целочисленное значение (int), соответствующее одной из предопределенных констант.

Примеры использования функции
Проверка статуса после подключения
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
$status = pg_transaction_status($conn);

echo 'Статус: ';
switch ($status) {
    case PGSQL_TRANSACTION_IDLE:
        echo 'Сервер ожидает команду';
        break;
    case PGSQL_TRANSACTION_ACTIVE:
        echo 'Сервер выполняет транзакцию';
        break;
    case PGSQL_TRANSACTION_INTRANS:
        echo 'Сервер находится в состоянии транзакции';
        break;
    case PGSQL_TRANSACTION_INERROR:
        echo 'Сервер находится в состоянии транзакции с ошибкой';
        break;
    case PGSQL_TRANSACTION_UNKNOWN:
        echo 'Соединение неактивно или сбой';
        break;
}
?>
Статус: Сервер ожидает команду
Наблюдение за статусом во время транзакции
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
echo 'До BEGIN: ' . pg_transaction_status($conn) . '\n';

pg_query($conn, 'BEGIN');
echo 'После BEGIN: ' . pg_transaction_status($conn) . '\n';

pg_query($conn, 'SELECT 1');
echo 'После SELECT: ' . pg_transaction_status($conn) . '\n';

pg_query($conn, 'COMMIT');
echo 'После COMMIT: ' . pg_transaction_status($conn) . '\n';
?>
До BEGIN: 0
После BEGIN: 1
После SELECT: 1
После COMMIT: 0
Похожие функции в PHP

Прямых аналогов для получения статуса транзакции в PGSQL не существует. Однако некоторые функции предоставляют косвенную информацию:

  • pg_connection_status($connection) - Возвращает статус самого соединения (PGSQL_CONNECTION_OK, PGSQL_CONNECTION_BAD). Показывает, активно ли соединение, но не состояние транзакции на сервере.
  • pg_result_status($result) - Возвращает статус результата запроса (PGSQL_EMPTY_QUERY, PGSQL_COMMAND_OK и т.д.). Полезен для анализа результата последней выполненной команды, но не глобального статуса транзакции.

Функцию pg_transaction_status предпочтительно использовать, когда требуется точное понимание состояния серверной транзакции, особенно в асинхронных или сложных сценариях управления соединением.

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

В psycopg2 явной функции для статуса транзакции нет, но состояние можно проверить через атрибуты соединения и использование connection.get_transaction_status().

import psycopg2
conn = psycopg2.connect("dbname=test user=postgres")
print(conn.get_transaction_status())  # 0 = IDLE
cur = conn.cursor()
cur.execute("BEGIN")
print(conn.get_transaction_status())  # 2 = INTRANS
conn.commit()
print(conn.get_transaction_status())  # 0 = IDLE
0
2
0
JavaScript (node-postgres)

В библиотеке pg статус транзакции не предоставляется явно. Управление осуществляется через запросы BEGIN/COMMIT и обработку ошибок в асинхронных функциях.

const { Client } = require('pg');
const client = new Client();
await client.connect();
// Явного статуса нет. Состояние определяется контекстом выполнения запросов.
await client.query('BEGIN');
// Транзакция активна
await client.query('COMMIT');
// Транзакция завершена

Pg transaction status в MySQL

В MySQL аналогом является команда SHOW SESSION STATUS LIKE 'tx_isolation' или проверка переменной @@session.transaction_read_only, но они показывают уровень изоляции, а не текущее состояние. Более близко состояние можно получить через SELECT @@in_transaction (в некоторых драйверах, например, для MySQLi).

Типичные ошибки
Передача неверного типа аргумента
<?php
$status = pg_transaction_status("not_a_connection");
var_dump($status);
?>
Warning: pg_transaction_status() expects parameter 1 to be resource, string given
Попытка использовать закрытое соединение
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");
pg_close($conn);
$status = pg_transaction_status($conn);
echo $status;
?>
2  // PGSQL_TRANSACTION_UNKNOWN, так как соединение недействительно
Неверная интерпретация констант

Ошибкой является прямое сравнение с числами без использования предопределенных констант, что снижает читаемость кода.

// Плохо
if (pg_transaction_status($conn) == 1) { /* код */ }
// Хорошо
if (pg_transaction_status($conn) === PGSQL_TRANSACTION_ACTIVE) { /* код */ }
Изменения в функции

Функция pg_transaction_status была добавлена в PHP начиная с версии 5.2.0. Значительных изменений в её поведении или сигнатуре в последних основных версиях PHP (включая PHP 8.x) не было. Она остается стабильным и неизменным API для работы с PostgreSQL.

Расширенные примеры
Мониторинг статуса в длительной транзакции
Пример php
<?php
$conn = pg_connect("host=localhost dbname=test user=postgres");

function logTransactionStatus($connection, $step) {
    $statusMap = [
        PGSQL_TRANSACTION_IDLE => 'IDLE',
        PGSQL_TRANSACTION_ACTIVE => 'ACTIVE',
        PGSQL_TRANSACTION_INTRANS => 'INTRANS',
        PGSQL_TRANSACTION_INERROR => 'INERROR',
        PGSQL_TRANSACTION_UNKNOWN => 'UNKNOWN'
    ];
    $code = pg_transaction_status($connection);
    echo "Шаг {$step}: {$statusMap[$code]} ({$code})\n";
}

logTransactionStatus($conn, 'Инициализация'); // IDLE
pg_query($conn, 'BEGIN WORK');
logTransactionStatus($conn, 'После BEGIN'); // INTRANS

// Имитация долгой операции
pg_query($conn, 'SELECT pg_sleep(0.1)');
logTransactionStatus($conn, 'После SELECT'); // INTRANS (может быть ACTIVE во время выполнения)

pg_query($conn, 'SAVEPOINT my_savepoint');
logTransactionStatus($conn, 'После SAVEPOINT'); // INTRANS

pg_query($conn, 'ROLLBACK TO SAVEPOINT my_savepoint');
logTransactionStatus($conn, 'После ROLLBACK TO SAVEPOINT'); // INTRANS

pg_query($conn, 'COMMIT');
logTransactionStatus($conn, 'После COMMIT'); // IDLE
?>
Обработка сбоя соединения
Пример php
<?php
// Предположим, соединение установлено
$conn = pg_connect("host=localhost dbname=test user=postgres");

// Имитация сбоя (например, остановка сервера БД)
// В реальности это может произойти асинхронно

// Попытка выполнить запрос на разорванном соединении
@pg_query($conn, 'SELECT 1');

// Проверка статуса транзакции после возможного сбоя
$txStatus = pg_transaction_status($conn);
$connStatus = pg_connection_status($conn);

if ($connStatus === PGSQL_CONNECTION_BAD || $txStatus === PGSQL_TRANSACTION_UNKNOWN) {
    echo "Соединение разорвано. Необходимо переподключение.\n";
    // Логика переподключения...
}
?>

PHP pg_transaction_status function comments

En
Pg transaction status Returns the current in-transaction status of the server