Разное

Postgresql ошибка создания временной директории: Проблема с установкой PostgreSQL | PostgreSQL

Содержание

Типичные ошибки при работе с PostgreSQL. Часть 1 / Блог компании Postgres Professional / Хабр

Чуть более месяца назад в Москве состоялась крупнейшая конференция постгресового сообщества PGConf.Russia 2019, собравшая в МГУ свыше 700 человек. Мы решили выложить видео и расшифровку лучших докладов. Выступление Ивана Фролкова с разбором типичных ошибок при работе с PostgreSQL было отмечено лучшим на конференции, поэтому мы начнем с него.

Для удобства мы разбили расшифровку на две части. В этой статье речь пойдет о непоследовательном именовании, о constraints, о том, где лучше сосредоточить логику — в базе или в приложении. Во второй части будут разобраны обработка ошибок, конкурентный доступ, неотменяемые операции, CTE и JSON.

В нашей компании я занимаюсь поддержкой клиентов по вопросам, связанным с приложениями, то есть помогаю в случаях проблем с соединениями, с оптимизацией запросов и прочими подобными вещами. Насмотрелся я приложений самых разных. Чего я только не видел! Может быть даже больше, чем хотелось бы. Часть из того, что я буду рассказывать, относится не только к PostgreSQL, а к любой базе, но кое-что прежде всего к PostgreSQL.

Главный вывод, который я смог сделать из того, что я видел, довольно неожиданный: фактически любое приложение при должной настойчивости можно заставить работать. Был замечательный проект (я не могу упоминать все компании, с которыми мы работали), в котором еще более замечательное приложение создавало таблицы миллионами. Выглядело это так: в понедельник система работает неплохо, а уже в пятницу она практически не работает. На выходные дни запускают VACUUM FULL, и в понедельник она опять работает хорошо. Оказывается, над PostgreSQL можно вот так издеваться, и всё это довольно долго будет жить и работать. Другой товарищ сделал странную вещь: у него всё было построено на триггерах, процедур не было вообще. То есть большую часть таблиц трогать нельзя, сделать что-либо не получалось, но и эта база жила.


Он объяснял это так: «база переходит из одного консистентного состояния в другое консистентное. Если я повторно вкачу данные, она сломается. Но так как у меня триггеры и уникальный ключ, я данные повторно вкатить не могу». Подход дикий, но в то же время некоторый смысл в этом есть. Может, делать надо было по-другому, но учитывать особенности заказчиков тоже надо. Первая ошибочка, о которой я буду говорить, это:

Вот реальный пример, с которым я сталкивался. На слайде вы видите, как именовалась одна и та же сущность в разных колонках. Можно было бы еще и с пробелами. Другие объекты именовались так же непоследовательно. Если вам что-то нужно взять в другой таблице, то нужно посмотреть, как оно там называется, то же самое ли это. Если у вас есть id_user и user_id в одной таблице, работа начинается с исследования: что бы это всё значило.

У других клиентов все объекты именовались так: две буквы, дальше пять цифр. Сразу скажу, это была не «1С». Зачем они так делали — не знаю: никакой логики в этом не прослеживалось, но мое дело оптимизировать запросы.

Еще пример: часть названий на русском, часть на нерусском, но с каким-то русским акцентом. Это затрудняет понимание и плодит новые ошибки. Сам я стараюсь называть колонки так, как будто рассчитываю на сервис, который из этих имен колонок будет автоматически делать нормальные названия столбцов в каком-нибудь отчете. В реальной жизни последовательно именовать, к сожалению, не очень получается — и у меня в том числе. Особенно это сложно при коллективной разработке. Но стремиться надо.

Еще важная причина именовать последовательно: имена объектов доступны через запросы к метаданным, то есть имена это тоже данные. Вы сможете написать запрос и выбрать, скажем, все картинки — вообще все картинки — из базы.

Понятные метаданные — это очень удобно. Особенно если учесть типичные проблемы с документацией — а по моему опыту документация обычно либо отсутствует, либо неполная, либо неверная, либо и то, и другое: потому что задача написать хорошую документацию по сложности сравнима с задачей написания самого кода. Так что лучше, когда код самодокументированный. И логичное, последовательное именование объектов этому способствует, а когда что-то непонятно, приходится писать код сниппета и смотреть, как это работает. Один раз это ничего, два — ничего, но когда ты весь день только этим и занимаешься, это выматывает.

Реальный случай: у очень серьезной организации, с которой мы работали, была база — документооборот на Oracle. Мы ее перенесли в Postgres. Одним из условий договора было то, что мы наложим FOREIGN KEYs. Их там не было и, к сожалению, наложить нам их не удалось: оказалось что в таблицах очень много каких-то «левых» строк, и что с ними делать, никто не знает, включая заказчика.

Когда нужно не progress-bar-ы смотреть, а работать с документами на выплату денег, то ситуация грустная. Очень хорошо помогает, когда по договору программист сам оплачивает ошибки, и желательно, чтобы суммы были большие — тогда просветление наступает в течение минут, наверное, пятнадцати. Сразу появляются constraint-ы, сразу всё начинает проверяться.

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

С другой стороны, часто можно услышать, что constraint-ы снижают производительность. Да, снижают, но, если вы хотите иметь корректные данные, для вас других вариантов просто нет. Если у вас приложение, учитывающее количество посещений магазина покупателями, то тогда могут остаться неточности, которые на статистике не особенно скажутся, а если мы считаем деньги, constraint-ы нужны обязательно.

Имена constraint-ы обычно генерируются ORM-ом или системой, и именованием constraint-ов обычно никто специально не заморачивается — а зря! Когда вы будете в дальнейшем обрабатывать ошибку, то по имени constraint-а, вы сможете дать внятное сообщение пользователю, классифицировать ошибку и сообщить, нужно ли повторно пытаться выполнить операцию, или что эту операцию выполнять уже не обязательно, или что повторять ее просто нельзя.

Еще одна вещь, которую я тоже не встречал, но которую очень рекомендую: на все важные финансовые (и не только финансовые) операции проверок должно быть как минимум две. Дело в том, что рано или поздно вы полезете что-то менять в коде, и очень может быть, что одну из проверок вы сломаете. Тогда вас спасет вторая. Если сделаете три — тоже неплохо.

Часто возникает вопрос: где проверять корректность данных. На клиенте или на сервере? По-моему, очевидно, что проверять нужно и там, и там. У вас ошибка в клиенте, тогда сервер не

пропустит, или у вас ошибка на сервере, тогда хотя бы клиент поможет отследить ее. Вопрос несколько дискуссионный, и мы плавно переходим к теме: где держать логику базы: в приложении или в базе?

В базе удобно потому, что, по моему опыту, бизнес регулярно выдает срочные правки: сию секунду убрать или вставить то-то и то-то. Если у вас логика в компилируемом коде, то вам нужно собрать, задеплоить, посмотреть, что получилось. Часто это уже просто невозможно. В базе это делать удобней. Но есть известный афоризм: опытные программисты на фортране пишут на фортране на любом языке. Процентов 80 серверного кода написаны совершенно в процедурном стиле: у нас есть функция «получить_юзера()» и она возвращает тип «юзер», а если «получить_список_юзеров()», то она возвращает массив «юзеров». На Java такие вещи писать действительно удобнее, чем на SQL или pgsql.

С другой стороны: зачем вам функция «получить_юзера()»? Вы просто берете его в таблице или в представлении. Раз у вас реляционная база, то и писать надо, как мне кажется, реляционно. Тут важно, во-первых, четко определиться с какими данными мы работаем: если данные у нас мусорные или полумусорные, то и результат будет соответствующий, и убиваться, наверное, особо не следует. Если данные для нас важны, если это деньги, имущество или юридические операции, то нужны constraint-ы и чем больше, тем лучше. Повторю: лучше не выполнить операцию, чем выполнить ее неправильно. И не надо писать процедурный код в реляционной базе: сильно пожалеете.

Я видел таблицу с 30 тысяч строк (товары), в которой запрос «покажите список актуальных товаров» выполнялся около секунды. Видимо, им удалось создать «красивую и сложную» схему БД. Лично я считаю, что, если вы делаете что-то сильно мудреное, то, скорее всего, вы либо делаете что-то не так, либо у вас действительно очень, очень сложная задача. Если у вас какой-нибудь магазин или обычное приложение для учета людей, то вряд ли там есть очень сложные взаимоотношения между сущностями.

Когда я начинал свой профессиональный путь, таблица в DBF-файле в 60 мегабайт в банковской системе казалась очень большой, а сейчас 60 мегабайт это вообще ничто — железо стало лучше, софт стал лучше, всё работает быстрее, но остается вопрос: откуда у вас столько данных? Очень большие, пухлые базы становятся такими обычно из-за архивов. В любой СУБД и в PostgreSQL много усилий потрачено на то, чтобы обеспечить консистентную конкурентную работу приложений. Архив скорее всего не меняется, и большинство возможностей СУБД для работы с ним вообще не нужны. Стоит подумать о вынесении его наружу СУБД.

То и дело с этаким комиссарским прищуром задают вопрос: а потянет ли PostgreSQL базу такого-то объема. Но тут сама постановка вопроса странная: положить данных в базу можно сколько угодно, сколько хватит места на диске, столько и будет лежать. Вопрос в том, как, например, бэкапить архивов в петабайт, куда вы положите полный backup и сколько вы будете его снимать. Я сильно подозреваю, что хотя бы частично эти требования к объемам связаны с желанием продавцов оборудования продать вам побольше.

Если вы храните документы в базе, вы их там обрабатывать вряд ли будете: экселевскую таблицу можно, конечно, модифицировать и на сервере, но это странное занятие. Скорее всего такие файлы будут вообще readonly. Лучше хранить ссылки на документы, а сами в каком-то внешнем хранилище. В конце концов можно хранить цифровую подпись таблицы — чтобы ее не поменяли (если вы решите соответствующие законодательные вопросы).

Еще такое наблюдение: если у вас не какой-то мега-мега бизнес, не какое-то, скажем, федеральное предприятие, то вряд ли у вас база сильно большая. Если вы не храните в ней видео, конечно.

Еще одна причина того, что база большая — ненужные индексы. Баз без индексов я не встречал, зато довольно часто встречал базы, где несколько индексов на одни и те же колонки в одном и том же порядке. База это позволяет сделать. Когда вы создаете индекс, пожалуйста, посмотрите, не дублирует ли он уже имеющийся. Посмотреть, какие индексы не нужны, можно, заглянув в pg_stat_user_indexes, чтобы понять насколько активно индекс используется. Может, он вообще не требуется.

Я натыкался и на ситуации (кстати, типичные), когда очень большая таблица не секционирована. Во всех СУБД большие таблицы лучше секционировать, но в PostgreSQL это особенно актуально из-за нашего любимого VACUUM-а. Я бы посоветовал секционировать таблицы начиная, наверное, со 100 гигабайт. Может быть начиная с 50. Я видел и несекционированные терабайтные таблицы, и они жили, правда, на SSD. Но это многовато, лучше было бы их порезать.

И еще одно наблюдение: практически все базы большого объема это архивы append only. Живые, меняющиеся данные попадаются в таких базах редко. Определитель с тем, что у вас — если архив, то можно подумать о том, как его вынести куда-то. И, кстати, можно к нему же из базы обеспечить доступ. Тогда и приложение менять не надо: для него ничего не изменится.

Некоторые из этих наблюдение из разряда «лучше быть богатым и здоровым, чем бедным и больным». Часто, во-первых, есть унаследованный код. Во-вторых, что-то неожиданное произошло, о чем-то не подумали, и получается что все не так красиво, как хотелось бы. Но тем не менее: не надо сильно мудрить. Помните, что если вы сильно мудрите, то, скорее всего, делаете что-то не то.

[Продолжение следует.]

Настройка continuous бекапов PostgreSQL / Хабр

В данном мануале описывается процесс настройки постоянного (continuous) бекапирования для баз данных PostgreSQL.

В нашей фирме (business to business) под каждого клиента создается свой собственный сервер, на который устанавливается база данных PostgreSQL и наш софт. Таким образом, у нас не единый instance продакшена, а десятки с разными экземплярами базы. Процесс настройки бекапов является частью процесса установки продакшена, а само бекапирование начинается до выхода системы в продакшен и продолжается в течение всего жизненного цикла сотрудничества с клиентом. Спецификацию железа и базового software определяем мы, поэтому все инстансы, как правило, имеют одни и те же версии Linux и PostgreSQL. Изредка этот инвариант нарушается — например, где-то по тем или иным причинам может стоять не Ubuntu, а Debian либо PostgreSQL более старой мажорной версии, чем у остальных. В последнем случае нужно быть особенно аккуратным — при возникновении сбоя следует иметь ввиду, что восстановление базы должно осуществляться на ту же мажорную версию PostgreSQL, на которой был сделан бекап, так как описываемый подход требует бинарной совместимости файлов данных, которая гарантируется только при переходе между минорными версиями PostgreSQL. Как поступить, если этот инвариант нарушен, также описано в конце данной статьи.

Подразумевается, что у читающего может быть довольно мало знаний как в области бекапов PostgreSQL, так и в сфере работы с Linux (а в особенности с инструментами ее командной строки), поэтому tutorial написан как можно более подробно.

Базовая концепция Continuous Archiving and Point-in-Time Recovery

В этом разделе укажем основные идеи, лежащие в основе подхода Continuous Archiving and Point-in-Time Recovery. При необходимости подробные детали можно найти в документации PostgreSQL.

Пожалуй, как и все СУБД, PostgreSQL имеет файлы данных, в которых хранит текущее состояние базы данных. Однако, кроме этого PostgreSQL ведет и сохраняет логи изменений в базе данных. Эти логи представлены в виде так называемых write ahead logs (WAL) файлов, которые сохраняются в подпапке pg_wal директории с данными:

WAL-файлы используются PostgreSQL для защиты от сбоев. Упрощенно говоря, при коммите транзакции PostgreSQL убеждается, что именно изменения в соответствующем WAL-файле гарантированно сохранились на диск, но, вообще говоря, может не делать такую же проверку по отношению к файлам с данными, например, кешируя их изменения до определенного момента в оперативной памяти. Если после последнего гарантированного сохранения файлов данных на диск (checkpoint) произошел сбой и текущее состояние еще не было сохранено, то после восстановления работы PostgreSQL возьмет последний checkpoint файлов данных (назовем его base backup) и последовательно применит к нему изменения, сохраненные в WAL-файлах (replay log entries).

Вышеописанную модель также можно использовать и для бекапирования с последующим восстановлением (например) на другом сервере. Для этого, очевидно, требуется реализовать следующую схему:

  1. Сначала (один раз) снять бекап файлов данных (и отправить файлы в безопасное место на другой сервер)
  2. В процессе работы по мере появления WAL-файлов тоже их бекапить

Модель восстановления после сбоя, таким образом, тоже становится очевидной:

  1. На новом сервере PostgreSQL загрузить файлы данных из бекапа (упрощенно это соответствует их простому копированию в соответствующую рабочую папку данных)
  2. На новом сервере PostgreSQL загрузить WAL-файлы из бекапа (упрощенно это соответствует их простому копированию в соответствующую подпапку рабочей папки данных)

Стоит иметь ввиду следующие особенности рассматриваемой модели бекапов:

  • Бекапятся сразу все базы данных текущего PostgreSQL-сервера, т.е. нет возможности забекапить, например, только одну из них
  • Не обязательно накатывать на base backup все записи WAL-файлов, можно остановиться на каком-то временном моменте (point-in-time recovery). Эта фича позволяет восстановить базу и в том случае, если сбой произошел в виду программной ошибки (например, была удалена какая-то таблица посредством drop table и т.п.).

В следующих разделах описываются технические детали описанной схемы.

Для этой цели будут использоваться следующие наименования: целевой сервер — текущий рабочий сервер, с которого делаем бекапы, сервер бекапов — сервер на который отправляются бекапы, новый сервер — сервер, на котором восстанавливается бекап целевого сервера после сбоя.

Оффтоп: несколько слов по безопасности

Ввиду особой ценности бекапов для бизнеса как с точки зрения восстановления после сбоев, так и с точки зрения возможных утечек информации нелишним будет пройтись по базовой безопасности Linux серверов. В целом, это не относится напрямую к рассматриваемой теме, поэтому, можно просто пробежаться глазами по этому разделу и, если у вас все устроено так же, спокойно пойти дальше. В случае если ваши решения по безопасности лучше описанных — просьба отписаться в комментариях и рассказать о своем опыте. Если же вы считаете, что с безопасностью у вас хуже, то описанные ниже решения стоит, вероятно, как можно скорее применить и к вашим продакшенам. Рассматриваться будет Ubuntu 18.04, на других версиях Linux инструкция может отличаться.

  1. Ваша система имеет последние обновления
    sudo apt-get update && sudo apt-get upgrade
  2. Вы не работаете от пользователя ‘root’, вместо этого у вас создан персонифицированный (то есть, для каждого сотрудника, которому требуется доступ на сервер, свой) пользователь в группе sudo (в нашем случае, назовем его alex)
    sudo adduser alex
    # Вводим пароль и др. данные типа Full Name и т.п.
    sudo adduser alex sudo
    # Для проверки успешности создания пользователя можно зайти от него...
    sudo su - alex
    # ...и посмотреть список файлов в /root, куда имеют доступ только sudoers
    sudo ls -la /root
    # Если же ввести команду без sudo, то должна возникнуть ошибка авторизации
    ls -la /root
  3. При подключении по SSH вы не используете авторизацию по логину/паролю, применяя вместо этого доступ по ключу
    # ---Локальная машина сотрудника---
    # Считаем, что сотрудник на локальной машине сгенерировал пару приватный/публичный ключ,
    # например, так, если у сотрудника Linux:
    ssh-keygen -t rsa -b 4096
    # При этом парольную фразу при генерации ключа сотрудник не оставил пустой, а установил достаточно сложный пароль
    # ---Продакшен, пользователь alex---
    # Создадим файл публичного ключа и сохраним туда содержимое публичного ключа с локальной машины сотрудника
    nano ~/alex.pub
    # Затем скопируем открытый ключ в authorized_keys
    mkdir -p ~/.ssh
    touch ~/.ssh/authorized_keys
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/authorized_keys
    cat ~/alex.pub >> ~/.ssh/authorized_keys
    rm ~/alex.pub
    # Перезагрузим сервер
    sudo reboot
  4. В конфиге ssh включена опция доступа по ключу, кроме этого порт доступа ssh изменен со стандартного на рандомный (макроподстановка [generatedPortNumber] в скрипте ниже) в диапазоне от 1024 до 57256 (т.к. часто сканеры портов для экономии ресурсов проверяют лишь стандартные порты)
    # Открыть файл настроек ssh
    sudo nano /etc/ssh/sshd_config
    # Раскоментировать и поменять значения следующих ключей:
    PubkeyAuthentication yes
    # Если в файле присутствует ключ AuthenticationMethods, то в этом (и только в этом!) случае 
    # поменять его значение или раскоментировать
    AuthenticationMethods publickey
    # Поменять значение порта на [generatedPortNumber] и раскоментировать
    Port [generatedPortNumber]
    # Перезагрузиться
    sudo reboot
    # --- После перезагрузки ---
    # Убедиться в успешности подключения по ssh на новый порт по ключу пользователя alex...
  5. Доступ root-а по ssh — запрещен, доступ по паролю по ssh — запрещен
    # Открыть файл настроек ssh
    sudo nano /etc/ssh/sshd_config
    # Раскоментировать и поменять значения следующих ключей:
    PermitRootLogin no
    ChallengeResponseAuthentication no
    PasswordAuthentication no
    UsePAM no
    # Перезагрузиться
    sudo reboot

Настройка сервера бекапов

Создание папок для бекапа

Поскольку у нас множество инсталляций, с которых будут собираться бекапы, структура папок будет следующей. Папка для хранения бекапов — /var/lib/postgresql/backups. Под каждую инсталляцию в папке для хранения бекапов создается подпапка по имени клиента [clientName]. В каждой такой подпапке будут лежать 2 папки: base для базового бекапа и wal для continious archiving WAL-файлов с целевого сервера. Таким образом, при настройке бекапирования для клиента [clientName] выполняем следующие команды по созданию соответствующих директорий:

sudo mkdir -p /var/lib/postgresql/backups/[clientName]/base
sudo mkdir -p /var/lib/postgresql/backups/[clientName]/wal

Разумеется, структура папок может быть и любой другой, которую вы находите более удобой для вас. Например, если хранить бекапы в home директориях соответствующих пользователей (см. ниже), то в следующем пункте можно сэкономить пару команд по раздаче прав на чтение и запись в эти папки.

Создание пользователя

В целях безопасности каждый продакшен (целевой сервер), с которого идут бекапы, будет иметь своего собственного пользователя на сервере бекапов. Это — обычный пользователь с ограниченными правами (не sudoer), который должен иметь права на чтение и запись в свою папку для бекапа, но не иметь возможность ни читать, ни писать в папки чужих продакшенов. Таким образом, даже если данный целевой сервер будет скомпрометирован, это не приведет к утечке данных других продакшенов через сервер бекапов.

Подробнее процесс выглядит следующим образом. Допустим, мы настраиваем бекап для проекта с именем foo. Для настройки сервера бекапов изначально заходим на него от пользователя из sudo. Добавляем пользователя с ограниченными правами foobackup:

# Добавить нового пользователя
sudo adduser foobackup
Adding user `foobackup' ...
Adding new group `foobackup' (1001) ...
Adding new user `foobackup' (1001) with group `foobackup' ...
Creating home directory `/home/foobackup' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for foobackup
Enter the new value, or press ENTER for the default
        Full Name []: AlexGtG
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y

Выдача прав пользователю на папки бекапа

Разрешаем foobackup читать и писать в свою папку, но запрещаем это делать всем остальным:

# Владельцем папки foo назначается foobackup
sudo chown -R foobackup: /var/lib/postgresql/backups/foo
# Никто кроме владельца не имеет доступа к этой папке
sudo chmod -R 700 /var/lib/postgresql/backups/foo

Настройка публичных ключей

Для завершения настройки сервера бекапов нашему новому пользователю foobackup необходимо дать удаленный доступ, чтобы он имел возможность отсылать бекапы на сервер. Как и ранее, доступ будет осуществляться по ключам доступа и только по ним.

На целевом сервере бекапы делаются от имени пользователя postgres, соответственно генерируем (если этого не было сделано ранее) приватный и публичные ключи для него:

# Находясь на целевом сервере, в данном случае это сервер проекта foo,
# заходим от имени postgres
sudo su - postgres
# Генерируем новый приватный ключ (только если этого не было сделано ранее!)
ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/var/lib/postgresql/.ssh/id_rsa):
/var/lib/postgresql/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/lib/postgresql/.ssh/id_rsa.
Your public key has been saved in /var/lib/postgresql/.ssh/id_rsa.pub.

Копируем содержимое публичного ключа из указанного при генерации системой места (Your public key has been saved in…), в нашем случае это /var/lib/postgresql/.ssh/id_rsa.pub:

# По-прежнему находясь на целевом сервере под пользователем postgres откроем файл публичного ключа и скопируем его содержимое
vi /var/lib/postgresql/.ssh/id_rsa.pub

Сохраняем публичный ключ на сервер бекапов для пользователя foobackup:

# На сервере бекапов:
# Заходим от имени пользователя foobackup
sudo su - foobackup
#  В файл foobackup.pub cохранить содержимое открытого ключа, которое мы ранее скопировали
nano ~/foobackup.pub
# Затем записать открытый ключ пользователя в authorized_keys
mkdir -p ~/.ssh
touch ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
cat ~/foobackup.pub >> ~/.ssh/authorized_keys
rm ~/foobackup.pub

Проверка работоспособности копирования

Теперь проверим, что мы все сделали правильно. В нашей схеме за копирование бекапов с целевого сервера на сервер бекапов будет отвечать scp — утилита для копирования файлов на удаленный сервер с синтаксисом, аналогичным локальному аналогу — cp. В принципе, можно использовать и другие средства доставки файлов, например, rsync и т.п.

# Находясь на целевом сервере (по-прежнему под пользователем postgres):
# Заранее положим в папку /var/lib/postgresql/backups файл test.txt...
# и скопируем его в соотв. папки сервера бекапов:
scp /var/lib/postgresql/backups/test.txt foobackup@[backupServerIp]:/var/lib/postgresql/backups/foo/base
scp /var/lib/postgresql/backups/test.txt foobackup@[backupServerIp]:/var/lib/postgresql/backups/foo/wal

После копирования заходим на сервер бекапов и убеждаемся, что файл действительно скопировался, например, так:

test -f /var/lib/postgresql/backups/foo/base/test.txt && echo 'exists in base' || echo 'not exists in base'
test -f /var/lib/postgresql/backups/foo/wal/test.txt && echo 'exists in wal' || echo 'not exists in wal'

По окончании проверок файл test.txt следует удалить из соответствующих папок сервера бекапов.

Настройка целевого сервера

Конфигурация PostgreSQL

Архивирование без сжатия

В файле postgresql.conf (его расположение можно получить выполнив из psql команду «SHOW config_file;») сделать следующие изменения (с подстановкой [backupServerIp] = IP адрес сервера бекапов, [clientName] = foo):

#Раскоментировать и изменить строку с wal_level на следующее значение:
wal_level = replica
#Раскоментировать и изменить строку с archive_mode на следующую:
archive_mode = on
#Раскоментировать и изменить строку archive_command на следующее значение:
archive_command = 'cat %p | ssh foobackup@[backupServerIp] "set -e; test ! -f /var/lib/postgresql/backups/[clientName]/wal/%f; cat > /var/lib/postgresql/backups/[clientName]/wal/%f.part; sync /var/lib/postgresql/backups/[clientName]/wal/%f.part;  mv /var/lib/postgresql/backups/[clientName]/wal/%f.part /var/lib/postgresql/backups/[clientName]/wal/%f"'      # command to use to archive a logfile segment
#Раскоментировать и изменить строку archive_timeout на следующее значение:
archive_timeout = 3600

В archive_command сначала проверяется не существует ли уже на сервере бекапов файл с таким именем. Это одно из требований документации PostgreSQL, которое направлено на защиту от разрушения integrity бекапа из-за администраторских ошибок — когда, например, бекапирование с двух разных серверов по ошибке настроено на одну и ту же папку. Далее происходит копирование файла по сети (scp) с использованием достаточно стандартного подхода: сначала поток записывается во временный файл и затем, только если он полностью скопирован и сброшен на диск (sync), меняется его имя (mv) с временного (.part) на постоянное. Если после переименования файла случилась ошибка и метаданные о таком переименовании не были сброшены на диск, то скрипт вернется с ошибкой и PostgreSQL просто повторит отправку файла. Ошибка на любом шаге скрипта закончит весь скрипт с ненулевым кодом (set -e).

Каждый WAL-файл занимает 16Mb и его архивирование (в нашем случае «архивирование» — это отправка на сервер бекапов) происходит только после того, как он заполнен. Таким образом, если данный клиент генерирует мало трафика БД, то бекап текущего WAL-файла может не происходить недетерменированно долго. Чтобы иметь возможность при сбое восстановить версию базы, например, не более часовой давности, необходимо в archive_timeout задать время форсированного архивирования (промежуток, через который даже неполный WAL-файл архивируется) в 1 час — в секундах это 3600. Не следует устанавливать слишком малые значения, потому что даже неполные WAL-файлы занимают 16Mb — таким образом, в заданный промежуток времени не менее 16Мб данных будет уходить на сервер бекапов. Например, при archive_timeout равном одному часу, в сутки на сервер бекапов будет уходить не менее 384Мб данных, в неделю это больше 2Gb.

Архивирование со сжатием

Учитывая возможные проблемы с разрастанием размера бекапов можно сразу делать сжатие и на сервер бекапов отправлять уже сжатые WAL-файлы (на своих продакшенах мы делаем именно так). В таком случае команда archive_command будет выглядеть так:

archive_command = 'gzip -c -9 %p | ssh foobackup@[backupServerIp] "set -e; test ! -f /var/lib/postgresql/backups/[clientName]/wal/%f.gz; cat > /var/lib/postgresql/backups/[clientName]/wal/%f.gz.part; gzip -t /var/lib/postgresql/backups/[clientName]/wal/%f.gz.part; sync /var/lib/postgresql/backups/[clientName]/wal/%f.gz.part;  mv /var/lib/postgresql/backups/[clientName]/wal/%f.gz.part /var/lib/postgresql/backups/[clientName]/wal/%f.gz"'       # command to use to archive a logfile segment

После сделанных в postgresql.conf изменений необходимо перезапустить PostgreSQL:

sudo service postgresql restart

Создание базового бекапа

Создание базового бекапа делается утилитой pg_basebackup, которая была установлена на целевом сервере вместе с PostgreSQL. Предполагается, что в PostgreSQL целевого сервера создан некий trusted пользователь с привилегиями, достаточными для осуществления бекапа всех баз данных на текущей инсталляции PostgreSQL (к примеру, это может быть администраторский аккаунт, используемый для обслуживания баз данных, или отдельный пользователь, специально созданный для создания базовых бекапов). Имя этого пользователя должно быть использовано в подстановке [trusted db user]. В процессе выполнения команды будет запрошен пароль этого пользователя. После создания бекапа сразу отправляем его на сервер бекапов.

#На целевом сервере:
sudo -i -u postgres
pg_basebackup --pgdata=/tmp/backups --format=tar --gzip --compress=9 --label=base_backup --host=127.0.0.1 --username=[trusted db user] --progress --verbose
#При успехе в /tmp/backups будут созданы файлы base.tar.gz и pg_wal.tar.gz,
#которые скопируем на сервер бекапов
scp /tmp/backups/base.tar.gz /tmp/backups/pg_wal.tar.gz foobackup@[backupServerIp]:/var/lib/postgresql/backups/[clientName]/base
exit

Ключи —progress и —verbose не являются обязательными и используются для наглядности наблюдения процесса создания бекапа — при наличии этих ключей PostgreSQL выдает некоторую дополнительную информацию в консоль в удобочитаемом виде.

Восстановление бекапа

Проверка работоспособности бекапирования

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

  1. Базовый бекап отправлен на сервер бекапов
  2. WAL-файлы отправляются на сервер бекапов

П.1 проверяется так: на сервере бекапов заходим в папку /var/lib/postgresql/backups/foo/base и убеждаемся, что она содержит файлы base.tar.gz и pg_wal.tar.gz:

Чтобы быстро — без долгого времени наблюдения за системой — проверить п.2, вернемся в пункт настройки PostgreSQL и поменяем таймаут архивирования (archive_timeout) на 60 секунд, затем рестартуем PostgreSQL. Теперь при наличии изменений в базе WAL-файлы будут архивироваться не реже, чем раз в минуту. Далее в течение некоторого времени (3-5 минут) будем любым (безопасным) образом генерировать изменения в базе — например, мы делаем это просто через наш фронт, вручную создавая активность тестовыми пользователями.

Параллельно нужно наблюдать за папкой /var/lib/postgresql/backups/foo/wal сервера бекапов, где примерно раз в минуту будет появляться новый файл:

После проверки очень важно вернуть archive_timeout в продакшен значение (у нас в зависимости от клиента это минимум 1 час, т.е. 3600, максимум — сутки, т.е. 86400).

Если видно, что файлы не отправляются на сервер бекапов, то исследование проблемы можно начать с анализа логов PostgreSQL, лежащих здесь /var/log/postgresql. Например, если пара приватный-публичный ключ была настроена неверно, то можно увидеть подобную запись в файле postgresql-10-main.log (название лог-файла зависит от устанавливаемой версии):

2019-09-02 15:48:52.503 UTC [12983] DETAIL:  The failed archive command was: scp pg_wal/00000001000000000000003B [fooBackup]@[serverBackupIp]:/var/lib/postgresql/backups/foo/wal/00000001000000000000003B
Host key verification failed.
lost connection

Восстановление из бекапа

Пусть у нас заранее подготовлен новый сервер, где установлен PostgreSQL той же мажорной версии, что и на целевом сервере. Также предположим, что с сервера бекапов мы предварительно скопировали папку бекапа /var/lib/postgresql/backups/foo на новый сервер по тому же пути.

Далее по шагам описана процедура развертывания этого бекапа на новом сервере.

Выясняем путь, по которому хранятся файлы данных:

#Находясь в psql:
show data_directory;

В зависимости от версии PostgreSQL выдастся что-то подобное: /var/lib/postgresql/10/main

Удаляем все содержимое папки с данными:

#Останавливаем инстанс сервера, на который будем накатывать бекап
sudo service postgresql stop
sudo rm -rf /var/lib/postgresql/10/main/*

Останавливаем инстанс PostgreSQL на ЦЕЛЕВОМ сервере:

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

sudo service postgresql stop

Распаковываем файлы из бекапа в папку данных PostgreSQL:

Здесь и далее снова работаем с новым сервером.

sudo tar xvzf /var/lib/postgresql/backups/[clientName]/base/base.tar.gz -C /var/lib/postgresql/10/main
sudo tar xvzf /var/lib/postgresql/backups/[clientName]/base/pg_wal.tar.gz -C /var/lib/postgresql/10/main

Ожидается, что команда tar, запущенная от sudo, сохранит group и ownership распакованных файлов за пользователем postgres — это важно, поскольку далее их будет использовать PostgreSQL, работающий именно от этого пользователя.

В папке с данными создаем конфиг восстановления:

Если сжатия на шаге архивирования WAL-файлов не было:

nano /var/lib/postgresql/10/main/recovery.conf
#Добавить нужно единственную строку, заменив [clientName] на актуальное наименование инсталляции (в нашем примере [clientName] = foo)
restore_command = 'cp /var/lib/postgresql/backups/[clientName]/wal/%f %p'

#Выйти из nano c сохранением результатов и назначить права на файл пользователю postgres
sudo chown postgres:postgres /var/lib/postgresql/10/main/recovery.conf
sudo chmod 600 /var/lib/postgresql/10/main/recovery.conf

#Назначить права на папку с бекапом WAL-файлов и ее содержимое (с подстановкой [clientName] = foo)
sudo chown -R postgres:postgres /var/lib/postgresql/backups/[clientName]/wal
sudo chmod 700 /var/lib/postgresql/backups/[clientName]/wal
sudo chmod 600 /var/lib/postgresql/backups/[clientName]/wal/*

Если сжатие на шаге архивирования WAL-файлов было, то restore_command должен выглядеть следующим образом (все остальное не меняется):

restore_command = 'gunzip -c /var/lib/postgresql/backups/[clientName]/wal/%f.gz > %p'

Запускаем PostgreSQL:

sudo service postgresql start

Обнаружив в папке с данными конфиг восстановления, PostgreSQL входит в режим восстановления и начинает применять (replay) WAL-файлы из архива. После окончания восстановления recovery.conf будет переименован в recovery.done (поэтому очень важно на предыдущем шаге дать пользователю postgres права на изменение файла). После этого шага сервер PostgreSQL готов к работе. Если по внешним признакам видно, что база не восстановилась либо восстановилась только до уровня базового бекапа, то исследование проблемы можно начать с анализа логов PostgreSQL, лежащих здесь /var/log/postgresql. Например, если на предыдущем шаге не были даны права пользователю postgres на папку с бекапом WAL-файлов, то можно увидеть подобную запись в файле postgresql-10-main.log (название лог-файла зависит от устанавливаемой версии):

2019-09-04 11:52:14.532 CEST [27216] LOG:  starting archive recovery
cp: cannot stat '/var/lib/postgresql/backups/foo/wal/0000000100000000000000A8': Permission denied

Перенос PostgreSQL базы данных между разными мажорными версиями

В этом параграфе, как и было обещано в начале статьи, рассмотрим случай, когда требуется перенести базу с одной мажорной версии на другую. Поскольку основным сценарием бекапирования для нас является подход, описанный выше, то здесь мы будем предполагать, что целевой сервер доступен и работоспособен — то есть, перенос базы нужно осуществить не из-за сбоя, а по другим (организационным) причинам.

Будем использовать утилиту pg_dump или pg_dumpall. Обе они генерируют набор SQL-команд. Первая используется для создания бекапа конкретной базы данных, а вторая — при бекапе всего кластера. В последнем случае, кроме баз данных кластера копируются еще и его глобальные объекты — например, роли, что позволяет затем после развертывания бекапа не делать дополнительных действий в виде создания недостающих ролей, раздачи привилегий и т.п.

Создание дампа

На целевом сервере выполнить (желательно, чтобы на этот момент потребители его баз данных были остановлены и/или не проявляли активность по отношению к БД):

# Входим от имени пользователя postgres или от другого пользователя, являющегося админом текущего кластера PostgreSQL
sudo -i -u postgres
# Делаем дамп с опцией -с - при этой опции существующие при накатывании дампа объекты на целевом сервере будут удалены,
#здесь foo.dump.gz - путь, по которому будет сохранен дамп.
pg_dumpall -c | gzip -c > /tmp/backups/foo.dump.gz

Накатывание дампа

Будем считать, что на новый сервер по тому же пути (/tmp/backups/foo.dump.gz) скопирован сделанный на предыдущем шаге дамп.

Находясь на новом сервере:

# Входим от имени пользователя postgres, являющегося админом текущего кластера PostgreSQL
sudo -i -u postgres
#Накатим дамп на текущий кластер, выведем лог работы (включая ошибки) в файл /tmp/backups/foo.restore.out
gunzip -c /tmp/backups/foo.dump.gz | psql -d postgres &> /tmp/backups/foo.restore.out

После окончания восстановления бекапа нужно просмотреть лог восстановления. По умолчанию psql работает с выключенным флагом ON_ERROR_STOP, поэтому при возникновении ошибок скрипт не прерывается, а продолжает работу. Ниже перечислены те ошибки, которые не являются проблемными, при появлении же в логе других ошибок следует считать восстановление базы не успешным.

#Если мы накатываем дамп на новый кластер, то целевой базы может не существовать, тогда появится ошибка
ERROR:  database "foo" does not exist
#Это не проблема, так как дамп содержит команду по созданию базы данных, однако, нужно убедиться, что далее по скрипту база создалась и подключение к ней успешно. Об этом говорит строка:
You are now connected to database "foo" as user "postgres".
#Дамп, созданный с ключом -c (clean) содержит команды пересоздания ролей: сначала производится попытка удалить роль, а затем создать ее заново.
#Эта команда будет неуспешной для текущего пользователя, от которого работает psql, в данном случае это postgres, поэтому в логах встретится такая ошибка:
ERROR:  current user cannot be dropped
#Отметим, что даже если работать не от пользователя postgres, а, например, специально для целей накатывания бекапа создать нового пользователя, и работать от него, то все равно будет иметь место ошибка удаления роли postgres, так как эта роль требуется для работоспособности кластера.
#Поскольку роль postgres не была удалена, то далее при попытке ее создания будет выдана ошибка:
ERROR:  role "postgres" already exists
#Внимание! Более никаких ошибок в логе восстановления базы данных встретиться не должно!

Включение сервисов

После окончания накатывания дампа нужно:

  1. Настроить бекапирование нового сервера
  2. Переключить соответствующие сервисы на новый адрес базы данных и включить их для пользователя

После этого перенос можно считать завершенным.

PostgreSQL : Документация: 11: 19.8. Регистрация ошибок и протоколирование работы сервера : Компания Postgres Professional

log_destination (string)

PostgreSQL поддерживает несколько методов протоколирования сообщений сервера: stderr, csvlog и syslog. На Windows также поддерживается eventlog. В качестве значения log_destination указывается один или несколько методов протоколирования, разделённых запятыми. По умолчанию используется stderr. Параметр можно задать только в конфигурационных файлах или в командной строке при запуске сервера.

Если в log_destination включено значение csvlog, то протоколирование ведётся в формате CSV (разделённые запятыми значения). Это удобно для программной обработки журнала. Подробнее об этом в Подразделе 19.8.4. Для вывода в формате CSV должен быть включён logging_collector.

Если присутствует указание stderr или csvlog, создаётся файл current_logfiles, в который записывается расположение файла(ов) журнала, в настоящее время используемого сборщиком сообщений для соответствующего назначения. Это позволяет легко определить, какие файлы журнала используются в данный момент экземпляром сервера. Например, он может иметь такое содержание:

stderr log/postgresql.log
csvlog log/postgresql.csv

current_logfiles переписывается когда при прокрутке создаётся новый файл журнала или когда изменяется значение log_destination. Он удаляется, когда в log_destination не задаётся ни stderr, ни csvlog, а также когда сборщик сообщений отключён.

Примечание

В большинстве систем Unix потребуется изменить конфигурацию системного демона syslog для использования варианта syslog в log_destination. Для указания типа протоколируемой программы (facility), PostgreSQL может использовать значения с LOCAL0 по LOCAL7 (см. syslog_facility). Однако, на большинстве платформ, конфигурация syslog по умолчанию не учитывает сообщения подобного типа. Чтобы это работало, потребуется добавить в конфигурацию демона syslog что-то подобное:

local0.*    /var/log/postgresql

Для использования eventlog в log_destination на Windows, необходимо зарегистрировать источник событий и его библиотеку в операционной системе. Тогда Windows Event Viewer сможет отображать сообщения журнала событий. Подробнее в Разделе 18.11.

logging_collector (boolean)

Параметр включает сборщик сообщений (logging collector). Это фоновый процесс, который собирает отправленные в stderr сообщения и перенаправляет их в журнальные файлы. Такой подход зачастую более полезен чем запись в syslog, поскольку некоторые сообщения в syslog могут не попасть. (Типичный пример с сообщениями об ошибках динамического связывания, другой пример — ошибки в скриптах типа archive_command.) Для установки параметра требуется перезапуск сервера.

Примечание

Можно обойтись без сборщика сообщений и просто писать в stderr. Сообщения будут записываться в место, куда направлен поток stderr. Такой способ подойдёт только для небольших объёмов протоколирования, потому что не предоставляет удобных средств для организации ротации журнальных файлов. Кроме того, на некоторых платформах отказ от использования сборщика сообщений может привести к потере или искажению сообщений, так как несколько процессов, одновременно пишущих в один журнальный файл, могут перезаписывать информацию друг друга.

Примечание

Сборщик спроектирован так, чтобы сообщения никогда не терялись. А это значит, что при очень высокой нагрузке, серверные процессы могут быть заблокированы при попытке отправить сообщения во время сбоя фонового процесса сборщика. В противоположность этому, syslog предпочитает удалять сообщения, при невозможности их записать. Поэтому часть сообщений может быть потеряна, но система не будет блокироваться.

log_directory (string)

При включённом logging_collector, определяет каталог, в котором создаются журнальные файлы. Можно задавать как абсолютный путь, так и относительный от каталога данных кластера. Параметр можно задать только в конфигурационных файлах или в командной строке при запуске сервера. Значение по умолчанию — log.

log_filename (string)

При включённом logging_collector задаёт имена журнальных файлов. Значение трактуется как строка формата в функции strftime, поэтому в ней можно использовать спецификаторы % для включения в имена файлов информации о дате и времени. (При наличии зависящих от часового пояса спецификаторов % будет использован пояс, заданный в log_timezone.) Поддерживаемые спецификаторы % похожи на те, что перечислены в описании strftime спецификации Open Group. Обратите внимание, что системная функция strftime напрямую не используется. Поэтому нестандартные, специфичные для платформы особенности не будут работать. Значение по умолчанию postgresql-%Y-%m-%d_%H%M%S.log.

Если для задания имени файлов не используются спецификаторы %, то для избежания переполнения диска, следует использовать утилиты для ротации журнальных файлов. В версиях до 8.4, при отсутствии спецификаторов %, PostgreSQL автоматически добавлял время в формате Epoch к имени файла. Сейчас в этом больше нет необходимости.

Если в log_destination включён вывод в формате CSV, то к имени журнального файла будет добавлено расширение .csv. (Если log_filename заканчивается на .log, то это расширение заменится на .csv.)

Задать этот параметр можно только в postgresql.conf или в командной строке при запуске сервера.

log_file_mode (integer)

В системах Unix задаёт права доступа к журнальным файлам, при включённом logging_collector. (В Windows этот параметр игнорируется.) Значение параметра должно быть числовым, в формате команд chmod и umask. (Для восьмеричного формата, требуется задать лидирующий 0 (ноль).)

Права доступа по умолчанию 0600, т. е. только владелец сервера может читать и писать в журнальные файлы. Также, может быть полезным значение 0640, разрешающее чтение файлов членам группы. Однако, чтобы установить такое значение, нужно каталог для хранения журнальных файлов (log_directory) вынести за пределы каталога данных кластера. В любом случае нежелательно открывать для всех доступ на чтение журнальных файлов, так как они могут содержать конфиденциальные данные.

Задать этот параметр можно только в postgresql.conf или в командной строке при запуске сервера.

log_rotation_age (integer)

Определяет максимальное время жизни отдельного журнального файла, при включённом logging_collector. После того как прошло заданное количество минут, создаётся новый журнальный файл. Для запрета создания нового файла по прошествии определённого времени, нужно установить значение 0. Параметр можно задать только в конфигурационных файлах или в командной строке при запуске сервера.

log_rotation_size (integer)

Определяет максимальный размер отдельного журнального файла, при включённом logging_collector. После того как заданное количество килобайт записано в текущий файл, создаётся новый журнальный файл. Для запрета создания нового файла при превышении определённого размера, нужно установить значение 0. Задать этот параметр можно только в postgresql.conf или в командной строке при запуске сервера.

log_truncate_on_rotation (boolean)

Если параметр logging_collector включён, PostgreSQL будет перезаписывать существующие журнальные файлы, а не дописывать в них. Однако, перезапись при переключении на новый файл возможна только в результате ротации по времени, но не при старте сервера или ротации по размеру файла. При выключенном параметре всегда продолжается запись в существующий файл. Например, включение этого параметра в комбинации с log_filename равным postgresql-%H.log, приведёт к генерации 24-х часовых журнальных файлов, которые циклически перезаписываются. Параметр можно задать только в конфигурационных файлах или в командной строке при запуске сервера.

Пример: для хранения журнальных файлов в течение 7 дней, по одному файлу на каждый день с именами вида server_log.Mon, server_log.Tue и т. д., а также с автоматической перезаписью файлов прошлой недели, нужно установить log_filename в server_log.%a, log_truncate_on_rotation в on и log_rotation_age в 1440.

Пример: для хранения журнальных файлов в течение 24 часов, по одному файлу на час, с дополнительной возможностью переключения файла при превышения 1ГБ, установите log_filename в server_log.%H%M, log_truncate_on_rotation в on, log_rotation_age в 60 и log_rotation_size в 1000000. Добавление %M в log_filename позволит при переключении по размеру указать другое имя файла в пределах одного часа.

syslog_facility (enum)

При включённом протоколировании в syslog, этот параметр определяет значение «facility». Допустимые значения LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. По умолчанию используется LOCAL0. Подробнее в документации на системный демон syslog. Параметр можно задать только в конфигурационных файлах или в командной строке при запуске сервера.

syslog_ident (string)

При включённом протоколировании в syslog, этот параметр задаёт имя программы, которое будет использоваться в syslog для идентификации сообщений относящихся к PostgreSQL. По умолчанию используется postgres. Задать этот параметр можно только в postgresql.conf или в командной строке при запуске сервера.

syslog_sequence_numbers (boolean)

Когда сообщения выводятся в syslog и этот параметр включён (по умолчанию), все сообщения будут предваряться последовательно увеличивающимися номерами (например, [2]). Это позволяет обойти подавление повторов «— последнее сообщение повторилось N раз —», которое по умолчанию осуществляется во многих реализациях syslog. В более современных реализациях syslog подавление повторных сообщений можно настроить (например, в rsyslog есть директива $RepeatedMsgReduction), так что это может излишне. Если же вы действительно хотите, чтобы повторные сообщения подавлялись, вы можете отключить этот параметр.

Задать этот параметр можно только в postgresql.conf или в командной строке при запуске сервера.

syslog_split_messages (boolean)

Когда активен вывод сообщений в syslog, этот параметр определяет, как будут доставляться сообщения. Если он включён (по умолчанию), сообщения разделяются по строкам, а длинные строки разбиваются на строки не длиннее 1024 байт, что составляет типичное ограничение размера для традиционных реализаций syslog. Когда он отключён, сообщения сервера PostgreSQL передаются службе syslog как есть, и она должна сама корректно воспринять потенциально длинные сообщения.

Если syslog в итоге выводит сообщения в текстовый файл, результат будет тем же и лучше оставить этот параметр включённым, так как многие реализации syslog не способны обрабатывать большие сообщения или их нужно специально настраивать для этого. Но если syslog направляет сообщения в некоторую другую среду, может потребоваться или будет удобнее сохранять логическую целостность сообщений.

Задать этот параметр можно только в postgresql.conf или в командной строке при запуске сервера.

event_source (string)

При включённом протоколировании в event log, этот параметр задаёт имя программы, которое будет использоваться в журнале событий для идентификации сообщений относящихся к PostgreSQL. По умолчанию используется PostgreSQL. Параметр можно задать только в конфигурационных файлах или в командной строке при запуске сервера.

PostgreSQL не стартует, что необходимо исправить? — Хабр Q&A

Имеется:
Ubuntu 16.04.1 LTS

root@Ubuntu-1604-xenial-64-minimal ~ # uname -r
4.4.0-47-generic

PostgreSQL 9.5

root@Ubuntu-1604-xenial-64-minimal ~ # service postgresql status
● postgresql.service - LSB: PostgreSQL RDBMS server
   Loaded: loaded (/etc/init.d/postgresql; bad; vendor preset: enabled)
   Active: active (exited) since Thu 2016-12-01 02:21:43 UTC; 3 days ago
     Docs: man:systemd-sysv-generator(8)

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

При попытке подключиться к СУБД:

root@Ubuntu-1604-xenial-64-minimal ~ # psql -h localhost -p 5432 -U postgres -W
Password for user postgres: 
psql: could not connect to server: Connection refused
	Is the server running on host "localhost" (127.0.0.1) and accepting
	TCP/IP connections on port 5432?

Далее немного подробностей по командам — пустая выдача

root@Ubuntu-1604-xenial-64-minimal ~ # netstat -pant | grep postgres
root@Ubuntu-1604-xenial-64-minimal ~ #
root@Ubuntu-1604-xenial-64-minimal ~ # sudo su - postgres -c psql
psql: could not connect to server: No such file or directory
	Is the server running locally and accepting
	connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
root@Ubuntu-1604-xenial-64-minimal ~ # ps aux|grep postgres
root     29349  0.0  0.0  16976   936 pts/0    S+   12:00   0:00 grep --color=auto postgres

less /etc/postgresql/9.5/main/postgresql.conf

# - Connection Settings -

listen_addresses = '*'          # what IP address(es) to listen on;
                                        # comma-separated list of addresses;
                                        # defaults to 'localhost'; use '*' for all
                                        # (change requires restart)
port = 5432                             # (change requires restart)
max_connections = 100                   # (change requires restart)
#superuser_reserved_connections = 3     # (change requires restart)
unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories
                                        # (change requires restart)

В БД есть нужные данные, поэтому снести и заново поставить просто не могу(

Случилось это при перезагрузке сервера.
Что же делать, как же быть? Как все это починить?

Резервное копирование и восстановление в PostgreSQL / Хабр

Предположим что у нас есть postgresql в режиме потоковой репликации. master-сервер и hot-standby готовый заменить погибшего товарища. При плохом развитии событий, нам остается только создать trigger-файл и переключить наши приложения на работу с новым мастером. Однако, возможны ситуации когда вполне законные изменения были сделаны криво написанной миграцией и попали как на мастер, так и на подчиненный сервер. Например, были удалены/изменены данные в части таблиц или же таблицы были вовсе удалены. С точки зрения базы данных все нормально, а с точки зрения бизнеса — катастрофа. В таком случае провозглашение горячего hot-standby в мастера, процедура явно бесполезная…

Для предостережения такой ситуации есть, как минимум, два варианта…

  • использовать периодическое резервное копирование средствами pg_dump;
  • использовать резервное копирование на основе базовых копий и архивов WAL.

Первый способ достаточно прост в реализации и требует минимум усилий по установке и сопровождению. Ставим «pg_dump | lbzip2» в крон и забываем. Однако этот вариант не предлагает восстановить каталог базы данных на момент предшествующий сбою, алишь на момент выполнения бэкапа. Второй вариант чуть сложней и затратней в плане хранения, но этот вариант является более гибким решением в случае восстановления. О нем как раз и пойдет речь.
Из плюсов:

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

Минусы:

  • базовая копия занимает приблизительный размер кластера базы данных;
  • необходимость хранения WAL-архивов за период хранения базовой копии.

Как уже было сказано выше, этот способ резервного копирования предлагает гибкие возможности по восстановлению (можно восстановить состояния базы данных в четко указанный момент времени или в момент до или после выполнения определенной транзакции), но в то же время добавляет значительные требования к хранению резервных копий. Реализация выглядит следующим образом:

  • настройка режима архивирования WAL-логов;
  • настройка резервного копирования;
  • хранение одной или более резервных копий;
  • удаление самой старой резервной копии в случае успешного выполнения п.1;
  • удаление соответствующих WAL-архивов от резервной копии из п.3;
  • опционально можно проводить процедуру проверки резервных копий на предмет их «профпригодности».

Режим архивирования WAL-логов настраивается через включение параметров archive_mode и archive_command в postgresql.conf и создание директории где будут храниться архивы. Для начала стоит включить режим архивирования и оценить объем архивов создаваемых за одни сутки работы базы данных. Это позволит провести оценку требуемого места для хранения архивов и базовых копий. За архивирование отвечают опции:

archive_mode = on

archive_command = ‘cp %p /opt/pgsql/pgbackup/archive/%f’

Непосредственное резервное копирование настраиваем средствами pg_basebackup. Это программа из комплекта утилит идущих вместе с PostgreSQL которую можно использовать как для настройки потоковой репликации, так и для снятия резервных копий. Принцип работы позволяет снимать резервную копию не останавливая кластер базы данных. Исходя из задачи, нам всего лишь нужно запускать pg_basebackup по расписанию в cron. Учитывая требования по месту, нужно позаботиться о достаточном месте на диске, во избежание переполнения.

Хранение резервных копий задача опциональная, так как достаточно иметь хотя бы одну резервную копию. Подразумевается что на момент запуска создания резервной копии мы согласны с утверждением что база находится в «правильном» состоянии (мы ведь не будем копировать битую базу).

После завершения создания резервной копии, старую копию можно удалить вместе с архивами. Удаление архивов выполняется с помощью утилиты pg_archivecleanup. Утилита позволяет аккуратно удалить ненужные архивы основываясь на специальных файлах-метках, которые создаются при резервном копировании.

Также немаловажно настроить процедуру проверки резервной копии после её создания. Алгоритм достаточно простой: нужно скопировать базовую копию в некий каталог-песочницу (осторожно, место!), создать в ней минимально необходимые файлы конфигурации необходимые для запуска в режиме восстановления и запустить postgres относительно этого каталога-песочницы, после запуска необходимо проанализировать лог и сделать вывод является ли резервная копия пригодной для восстановления.

Таким образом процесс укладывается в три шага: создание базовой копии, её проверка и удаление старой, предыдущей базовой копии.

Теперь предположим что случилось наихудшее и нужно выполнить восстановление. Нужно остановить основной кластер postgres и переименовать каталог базы данных в произвольное имя. Каталог резервной копии нужно переименовать в каталог кластера базы данных. При необходимости скопировать файлы конфигурации. После определения конфигурационных файлов, запускаем postgres относительно нашего каталога. При запуске, Postgres обнаружит recovery.conf и запустится в режиме восстановления. Остается дождаться пока postgres восстановит свое состояние с помощью архивов, после чего можно будет подключаться к базе данных и продолжить работу. Вот и все, процедура восстановления завершена.

Вот так вот. Держите данные в сохранности! Скрипты для резервного копирования и валидации копий здесь.

невозможно создать временный каталог на ПК с Windows [FIX]

Автор Белов Олег На чтение 4 мин. Просмотров 399 Опубликовано

Как обычно, в основном для новых пользователей, каждый день возникает много сообщений об ошибках и уведомлений, особенно в Windows 10. Это конкретное исправление связано с тем, чтобы помочь вам устранить ошибку, возникшую при попытке создать временный каталог в Windows 10.

Ошибка при попытке создать временный каталог означает, что существует проблема с разрешениями вашей учетной записи пользователя. Эта ошибка обычно отображается с сообщением – невозможно выполнить файлы во временном каталоге.

Эта проблема обычно возникает, когда программное решение устанавливается через исполняемый файл. Когда отображается сообщение об ошибке, вам просто нужно закрыть его, но это не позволит вам продолжить установку. Эта ошибка может возникать в Windows 7, 8 и 10.

Это сообщение об ошибке означает, что ваша система была настроена на блокировку установки. Не нужно паниковать, потому что это только ошибка конфигурации, а не серьезная ошибка. Тем не менее, чтобы вы могли продолжить процесс установки, есть несколько вещей, которые вы можете сделать, чтобы исправить эту ошибку. Ниже приведено несколько методов, которые можно использовать для удаления сообщения об ошибке.

Что делать, если вы не можете создать временный каталог на ПК

Решение 1. Выберите Запуск от имени администратора.

Это должно быть очень быстрое решение для вас, если вы спешите завершить установку и у вас нет времени на более обширные решения. Как было сказано ранее, сигнал ошибки означает, что есть проблема с разрешениями.

Это можно легко обойти с помощью этих нескольких шагов:

  1. Ищите исполняемый файл, который вы хотите установить
  2. Щелкните правой кнопкой мыши по нему и в контекстном меню выберите «Запуск от имени администратора».

Это решение должно помочь вам очистить сообщение об ошибке и без проблем установить программное обеспечение.

– СВЯЗАННО: Как открыть временные файлы Интернета в Windows 10

Решение 2. Создайте новую папку Temp и измените переменные

Создание новой папки Temp и изменение переменных – лучший вариант, если сигнал ошибки ясно говорит о наличии проблемы с временным каталогом. Следуйте этим шагам внимательно и уберите ошибку с вашего пути:

  1. Введите диск C: и создайте новую папку, переименуйте ее в Temp (переключите C: с диска, на котором установлена ​​ваша ОС)
  2. Нажмите правой кнопкой мыши на Этот компьютер и выберите Свойства в контексте меню.
  3. С левой стороны вы увидите ссылку Дополнительные настройки , нажмите на нее
  4. Нажмите на вкладку “Дополнительно” в окне и выберите Переменные среды.
  5. Дважды щелкните TMP в пользовательских переменных
  6. Значение, которое вы увидите, должно быть % USERPROFILE% AppDataLocalTemp . Измените это на C: Temp. Затем закройте окно, нажав ОК.

В конце концов, попытайтесь установить программу, она должна работать без проблем.

Решение 3: Изменить контроль над папкой TEMP

  1. На диске, на котором установлена ​​ваша ОС, введите папку вашего пользователя и найдите папку AppData, в которой вы найдете локальную папку, если ваша ОС установлена ​​в разделе C: и вашим именем пользователя будет User, также адрес в проводнике должно быть указано « C: UsersUserAppDataLocal »
  2. Найдите папку Temp внутри, щелкните правой кнопкой мыши и выберите в меню свойства.
  3. В окне свойств нажмите Безопасность .
  4. В окне безопасности нажмите Все .
  5. Нажмите «Изменить» и убедитесь, что выбрано все поле «Полный доступ», затем нажмите «ОК» для сохранения.

Это должно дать вам полный доступ к папке Temp и решить проблему с ошибкой 5.

– СВЯЗАННО: Как удалить временные файлы с помощью Очистки диска в Windows 10, 8, 7

Решение 4. Подтвердите включение наследуемых разрешений в папку Temp

Как и в предыдущем решении, выполните следующие действия:

  1. На диске, на котором установлена ​​ваша ОС, введите папку вашего пользователя и найдите папку AppData, в которой вы найдете локальную папку, если ваша ОС установлена ​​в разделе C: и вашим именем пользователя будет User, также адрес в проводнике должно быть указано «C: UsersUserAppDataLocal»
  2. Найдите папку Temp внутри, щелкните правой кнопкой мыши и выберите в меню свойства.
  3. В окне свойств нажмите Безопасность .
  4. Нажмите «Дополнительно» для просмотра разрешений.
  5. В разрешениях должны быть СИСТЕМА, Администратор и Пользователь. Все они должны иметь полный контроль и наследоваться от C: UsersUser
  6. Найдите «Включить наследуемые разрешения» из родительского выбора этого объекта, нажмите «Продолжить», нажмите «Применить» и затем нажмите «ОК», чтобы сохранить настройку.

К настоящему времени у вас уже должен быть доступ для записи в каталог, который мгновенно исправит эту ошибку.

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

Несмотря на это, эти предложенные решения при правильном использовании позволят вам исправить ошибку невозможности создания временного каталога, встречающегося в Windows 10.

Ошибка установки Postgres чтение файла postgresql.conf — postgresql-9.2

У меня есть машина Windows Server 2003 , на которой я пытался установить Postgres 9.2 . В конце установки появляется предупреждающее сообщение

Проблема запуска шага после установки. Установка может не завершиться
правильно. Ошибка чтения файла C:\Program Files\PostgreSQL\9.2\data\postgresql.conf

Я проверил наличие файла postgresql.conf в C:\Program Files\PostgreSQL\9.2\data и обнаружил, что он не существует.

Я также обнаружил, что под папкой данных мало что есть, кроме папки pg_log , которая также пуста.

Есть какие-нибудь идеи о том, что я могу делать неправильно?

postgresql-9.2

Поделиться

Источник


Fawad Shah    

24 мая 2013 в 08:07

3 Ответа



12

Я рекомендую вам попробовать следовать, это сработало для меня:

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

Бежать:

initdb -D <your new data folder>

и затем:

pg_ctl -D <your new data folder> -l logfile start

Если проблема продолжается, и postgres установлен в разделе «Program Files», или путь установки содержит пробел, попробуйте использовать относительный путь для аргумента папки данных pg_ctl. Как например: «..\данные»

Поделиться


eaykin    

22 июня 2013 в 10:10



6

Я только что наткнулся на другую проблему: если имя пользователя текущего активного пользователя содержит символ пробела, postgres не сможет установить свои сервисы для начала, что приводит к тому же сообщению об ошибке. Будьте осторожны при изменении имени пользователя, так как это может повредить вашу установку windows. Вместо этого создайте нового пользователя с правами администратора и установите postgres оттуда , и все будет работать гладко.

Кроме того, вам придется использовать «runas /user:postgres cmd», чтобы получить командное окно, которое является хорошим, иначе initdb также не будет работать.

Я понимаю, что этот ответ запоздал на несколько месяцев, но он может помочь кому-то еще!

Поделиться


Kajetan Abt    

17 ноября 2013 в 17:56



0

Была эта проблема на Windows 10. Для меня решением было выбрать locale, отличный от [Default Locale] во время установки.

Поделиться


Vlad    

14 января 2019 в 00:13


Похожие вопросы:

Как изменить значения по умолчанию postgresql.conf на Openshift

Я запускал установку CakePHP на OpenShift в течение шести месяцев. База данных PostgreSQL 9.2, я использовал для установки файла postgresql.conf через shell, редактируя…

Рекомендуемый способ настройки max_prepared_transactions в Postgres на Kubernetes

Каков самый простой способ настроить параметр max_prepared_transactions=100 в docker kubernetes? Я использую изображение: https://hub.docker.com/_/postgres / Который имеет postgresql.conf файл в…

Создать пользователя postgres во время boot

Я запускаю файл bash из monit во время boot, этот файл bash запускает мой сервер postgres. если мой каталог базы данных отсутствует, я делаю: 1-initdb (postgresql/data/) Су — края -c…

по умолчанию postgresql.conf файл из docker

как я могу добраться до моего хоста postgresql.conf из контейнера? или где я могу увидеть значение по умолчанию? один сотрудник дал мне свой конфигурационный файл, чтобы сравнить его с моим…

chown: /var/lib/postgresql/data/postgresql.conf: файловая система только для чтения

Я решил проблему разрешения при установке /var/lib/postgresql/data , следуя этому ответу с initContainers . Теперь я пытаюсь использовать mount postgresql.conf в качестве Тома, и я сталкиваюсь с…

ошибка проверки подлинности пароля для пользователя » postgres»

Я успешно установил PostgreSQL server 8.4 на мой CentOS сервер. После этого я войду на сервер CentOS с помощью ‘postgres’ пользователя, но я не могу запустить ни одну команду, возникает ошибка:…

Ошибка удаленного доступа Postgres

Я пытаюсь установить удаленный доступ к моей базе данных, однако, когда я устанавливаю listen_addresses = ‘*’ , а затем пытаюсь перезапустить Postgres, у меня есть ошибка Error: Invalid line 59 in…

postgresql.conf max_prepared_transactions не работает

Я открыл свой файл postgresql.conf в папке данных postgres и изменил значение max_prepared_connections на ненулевое значение. Однако каждый раз, когда я пытаюсь использовать команду PREPARE…

Запуск PostgreSQL сервера не удался после модификации postgresql.conf с помощью команды sudo

Я хотел изменить параметр shared_buffers в моем файле postgresql.conf. Проблема в том, что я использовал команду sudo, и она дала право собственности на корневой каталог. -rw-rw-rw- 1 root root…

Не удается подключить postgres DB удаленно

Каждый раз, когда я пытаюсь подключиться к удаленному Postgres DB, я получаю ошибку: no pg_hba.conf entry for host 159.224.92.121, user xpkzxqrkisdrjd, database d92na0gp4bdq4, SSL off Я погуглил его…

PostgreSQL: связь [временная таблица] не существует ошибка для временной таблицы

Переполнение стека

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

.

psql — Postgresql не создает базу данных с «createdb» в качестве суперпользователя, но не выводит ошибки

Переполнение стека

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

Загрузка…

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *