Как не выполнить INSERT в транзакции только для чтения - PullRequest
0 голосов
/ 05 апреля 2020

Postgres сервер находится в режиме горячего резервирования. Используется асинхронная потоковая двоичная репликация.

Команда типа

INSERT INTO logfile (logdate) values (current_date)

Вызывает ошибку

не может выполнить INSERT в транзакции только для чтения.

Может быть, его следует изменить на

INSERT INTO logfile (logdate) 
SELECT current_date
WHERE   ???

Что, где следует использовать условие? Он должен работать, начиная с Postgres 9.0. Если прямое, где предложение невозможно, возможно, может использоваться некоторая функция plpg sql, где.

Может быть

show transaction_read_only

результат должен быть захвачен или какой-то может использоваться функция.

Альтернативно приложение может определить, доступна ли база данных только для чтения при запуске. Должен показывать результат транзакции для чтения.

1 Ответ

1 голос
/ 06 апреля 2020

Запуск INSERT на резервном сервере невозможен в чистом (непроцедурном) SQL, поскольку, когда сервер находится в режиме ожидания, все запросы на изменение данных отклоняются на этапе планирования до его выполнения.

Это возможно с условными выражениями в PL / Pg SQL.

DO $code$
BEGIN
  IF NOT pg_is_in_recovery() THEN
    INSERT INTO logfile (logdate) VALUES (current_date);
  END IF;
END;
$code$;

Однако, это, вероятно, не рекомендуется - обычно лучше один раз протестировать pg_is_in_recovery() (в коде приложения), а затем действовать соответственно.

Я использую системную функцию pg_is_in_recovery() вместо transaction_read_only GU C, потому что это не совсем то же самое. Но если вы предпочитаете это, пожалуйста, используйте:

SELECT current_setting('transaction_read_only')::bool

Дополнительная информация: Команда DO , условия в PL / Pg SQL, системная информация функции .

...