Комментарии 18
Начинали за здравие, закончили за упокой. Основное применение в логировании, но нельзя использовать, так как проблемы с производительностью. И чтоб не выстрелить себе в ногу в самом начале проекта, возьмите лучше вместо PostgreSQL Oracle.
0
А причем тут вообще savepoint? Это точка сохранения внутри одной транзакции. Автономная транзакция независима от родительской.
0
Ну, условно говоря, если у вас случилась ошибка вы прыгаете к сохраненному значению, а потом врубаете обработку ошибки (либо сперва вставляете обработку ошибки, а ву случае успешного прохождения этапа эту обработку ошибки удаляете).
Хотя я тут посмотрел — в функциях использование savepoint может вызывать (либо вызывает — тут уже смотреть надо) ошибку. Обходится RAISE EXCEPTION и блоком
EXCEPTION
WHEN RAISE_EXCEPTION THEN…
Хотя я тут посмотрел — в функциях использование savepoint может вызывать (либо вызывает — тут уже смотреть надо) ошибку. Обходится RAISE EXCEPTION и блоком
EXCEPTION
WHEN RAISE_EXCEPTION THEN…
0
Вы сейчас о конкретной задаче, применение автономных транзакций много шире. Конечно же вы можете логировать разными способами и обходить описанную проблему по-разному. Просто savepoint и автономные транзакции это разные вещи, они никак не связаны.
0
Они разные, разумеется. Просто мой подход (он, вообще говоря, как мне кажется годится не только для логирования)))) позволяет обойтись без PERFORM dblink_exec — а я подозреваю, что именно эта штука и тормозит. Причем тормозит за счет perform. Хотя, опять же, я могу и ошибаться.
Собственно — к сути разговора, когда вы пишете про проблемы с производительностью — какого они плана? Насколько оно тормозит? И на каком железе?
Исключительно шкурный интерес — если вы эту штуку тестировали, вы можете серьезно сэкономить мое время))))
Собственно — к сути разговора, когда вы пишете про проблемы с производительностью — какого они плана? Насколько оно тормозит? И на каком железе?
Исключительно шкурный интерес — если вы эту штуку тестировали, вы можете серьезно сэкономить мое время))))
0
dblink_exec работает медленно из-за того, что создается новое соединение с БД — а это процесс намного более дорогостоящий чем простая запись в таблицу. Поэтому использовать необходимо с умом. Приведу пример: предположим ваша функция состоит из следующих шагов: начало, большой длинный цикл, конец, обработка ошибок.
Вы логируете начало, конец и обработку ошибок с уровнями логирования «INFO» и «ERROR», а внутри цикла с уровнем «DEBUG». Чтобы функция работала как можно быстрее, вы можете отключить логирование с уровнем «DEBUG» (доработать функцию «log» для такого поведения не составит большого труда), и включать логирование «DEBUG» только если приперло и необходимо какое-то серьезное разбирательство.
То есть вы можете избежать потерь производительности просто с умом применяя этот прием, на это я и хотел обратить внимание в конце топика.
Вы логируете начало, конец и обработку ошибок с уровнями логирования «INFO» и «ERROR», а внутри цикла с уровнем «DEBUG». Чтобы функция работала как можно быстрее, вы можете отключить логирование с уровнем «DEBUG» (доработать функцию «log» для такого поведения не составит большого труда), и включать логирование «DEBUG» только если приперло и необходимо какое-то серьезное разбирательство.
То есть вы можете избежать потерь производительности просто с умом применяя этот прием, на это я и хотел обратить внимание в конце топика.
0
Понятно.
Кстати (подозрвеаю, что вам эта информация известна, а вот кому-то из читателей может помочь) — dblink позволяет открыть постоянное соединение — если соответствующим образом скомпоновать функцию, можно дополнительно увеличить производительность.
Кстати (подозрвеаю, что вам эта информация известна, а вот кому-то из читателей может помочь) — dblink позволяет открыть постоянное соединение — если соответствующим образом скомпоновать функцию, можно дополнительно увеличить производительность.
+3
Да, действительно, dblink_connect для создания persistent соединения и в дальнейшем его использование ощутимо ускорит работу.
Спасибо что указали на это, действительно важный момент.
Спасибо что указали на это, действительно важный момент.
+1
Что значит «прыгаете к сохраненному значению а потом врубаете обработку ошибок»? Вы по-моему не представляете себе ни как работает rollback to savepoint, ни вообще как обрабатываются исключения.
0
Вообще говоря — представляю. очень даже.
Там все вообще говоря просто — в блоке (если мы говорим о функции) мы присваиваем переменной некие значения. Например — про то, что следующий блок у нас завершился ошибкой. В следующем блоке мы меняем значение переменной. Как-то примерно так.
Либо, перед окончанием транзакции проверяем (по определенным, напрямую зависящим от транзакции критериям), что именно у нас сработало, а что — нет — (этот способ сравнительно легко гуглится) и обрабатываем результаты.
Но, как я уже писал выше, savepoint в функциях может вызывать (либо вызывает — еще раз вынужден повториться — поскольку сам я эту штуку не тестировал а из найденных обсуждений четкого вывода сделать тоже нельзя — я не знаю, может вызывать, или вызывает) ошибку SPI, посему правильнее и надежнее пользоваться
RAISE EXCEPTION
WHEN RAISE_EXCEPTION THEN
Там все вообще говоря просто — в блоке (если мы говорим о функции) мы присваиваем переменной некие значения. Например — про то, что следующий блок у нас завершился ошибкой. В следующем блоке мы меняем значение переменной. Как-то примерно так.
Либо, перед окончанием транзакции проверяем (по определенным, напрямую зависящим от транзакции критериям), что именно у нас сработало, а что — нет — (этот способ сравнительно легко гуглится) и обрабатываем результаты.
Но, как я уже писал выше, savepoint в функциях может вызывать (либо вызывает — еще раз вынужден повториться — поскольку сам я эту штуку не тестировал а из найденных обсуждений четкого вывода сделать тоже нельзя — я не знаю, может вызывать, или вызывает) ошибку SPI, посему правильнее и надежнее пользоваться
RAISE EXCEPTION
WHEN RAISE_EXCEPTION THEN
0
Что-то либо я не понимаю, либо вы бредите.
1. Как мы можем узнать текущем блоке узнать, «что следующий блок завершился ошибкой»?
Нужно в будущее заглядывать?
2. «Либо, перед окончанием транзакции проверяем (по определенным, напрямую зависящим от транзакции критериям), что именно у нас сработало, а что — нет — (этот способ сравнительно легко гуглится) „
Что такое “ перед окончанием транзакции»? Каким образом вы это определите? Вы в курсе, что если возникает исключение, то обработка прерывается, и переходит в блок исключений? Вы в курсе, что rollback to savepoint — это не «прыжок», как вы выразились, а откат изменений?
Вы в курсе, что нельзя переходить из блока исключений обратно в блок операторов?
Возможно, это я вас не понимаю. Может, если вы напишете код, то ситуация прояснится.
Например простая задача: вставить запись в таблицу, записать при этом в лог-таблицу — успешно она вставилась или нет.
1. Как мы можем узнать текущем блоке узнать, «что следующий блок завершился ошибкой»?
Нужно в будущее заглядывать?
2. «Либо, перед окончанием транзакции проверяем (по определенным, напрямую зависящим от транзакции критериям), что именно у нас сработало, а что — нет — (этот способ сравнительно легко гуглится) „
Что такое “ перед окончанием транзакции»? Каким образом вы это определите? Вы в курсе, что если возникает исключение, то обработка прерывается, и переходит в блок исключений? Вы в курсе, что rollback to savepoint — это не «прыжок», как вы выразились, а откат изменений?
Вы в курсе, что нельзя переходить из блока исключений обратно в блок операторов?
Возможно, это я вас не понимаю. Может, если вы напишете код, то ситуация прояснится.
Например простая задача: вставить запись в таблицу, записать при этом в лог-таблицу — успешно она вставилась или нет.
0
Вот за что люблю хабру — если в статье не очень круто ясен смысл, то в комментах всё разрулят и еще кучу всего расскажут ;)
+3
У вас source и message не экранируются, можно легко словить exception там, где не ожидаешь.
За статью спасибо, когда пару месяцев назад жалел об отсутствии автономных транзакций — думали в сторону dbms_pipe (есть в составе какого-то contrib-модуля) и постоянно запускающегося задания для job'а для получения и записи лога, про dblink не подумали.
Увы, job'ы в postgresql реализованы тоже так себе, чаще раза в две минуты штатными средствами запустить не удаётся. Данное решение отмели как либо ненадёжное (теряются сообщения при переполнении очереди), либо вызывающее проблемы с производительностью (sleep от процесса, записывающего лог, при переполнении очереди).
В итоге написали c-функцию, которая пишет лог в файл. Для нашей задачи это решение подходило, проблем с производительностью вроде нет :)
За статью спасибо, когда пару месяцев назад жалел об отсутствии автономных транзакций — думали в сторону dbms_pipe (есть в составе какого-то contrib-модуля) и постоянно запускающегося задания для job'а для получения и записи лога, про dblink не подумали.
Увы, job'ы в postgresql реализованы тоже так себе, чаще раза в две минуты штатными средствами запустить не удаётся. Данное решение отмели как либо ненадёжное (теряются сообщения при переполнении очереди), либо вызывающее проблемы с производительностью (sleep от процесса, записывающего лог, при переполнении очереди).
В итоге написали c-функцию, которая пишет лог в файл. Для нашей задачи это решение подходило, проблем с производительностью вроде нет :)
0
Да, pgagent не радует. Этот его 2-х минутный период сильно обламывает, не понимаю что им мешает добавить секунды в шедулер.
А насчет c-функции — мне логи все-таки хочется видеть в таблице. Это, конечно, вопрос вкуса, но мне например лень лезть в шелл и грепать файл вместо того, чтобы написать селект.
А насчет c-функции — мне логи все-таки хочется видеть в таблице. Это, конечно, вопрос вкуса, но мне например лень лезть в шелл и грепать файл вместо того, чтобы написать селект.
+1
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Автономные транзакции в PostgreSQL