PostgreSQL: Ответы на часто задаваемые вопросы начинающих DBA / FAQ for DBA beginners.
Ответы на часто задаваемые вопросы начинающих DBA / FAQ for DBA beginners.
❗ В первую очередь, мы должны уметь думать самостоятельно. В особенности, это касается проблем, которые у вас возникают — сначала тщательно и усердно попытайтесь нагуглить решение, и только в случае неудачи задавайте вопросы (как это делать правильно — см. ниже). Уважайте время и труд других участников сообщества, общайтесь исключительно в вежливой манере. Это первостепенные и необходимые условия для того, чтобы приумножать свои навыки и расти как профессионал.
У PostgreSQL прекрасное вежливое сообщество, которое обладает заметным свойством толерантности к начинающим участникам. Среди основных точек входа стоит отметить следующее:
Пожалуй, это наиболее частый вопрос у начинающих пользователей PostgreSQL, ежедневно звучащий в информационной среде сообщества.
Как правило, они получают ошибки, содержащие ключевые слова Connection refused
или Connection ... failed
. Например:
error: connection to server at "localhost", port 5432 failed: Connection refused
или (в случае попытки подключения через unix domain socket):
error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory
Is the server running locally and accepting connections on that socket?
Следует провести диагностику проблемы поэтапно (в настоящее время инструкция применительна только для Unix-based ОС):
Посмотреть, запущен ли основной процесс PostgreSQL, можно выполнив след. команду на сервере:
ps -ef | grep "postgresql.*config_file"
В случае, если PostgreSQL запущен, в выводе команды вы должны увидеть нечто вроде:
<PG_PATH> -D <DATA_DIR> -c config_file=<CONFIG_PATH>
Где <PG_PATH>
— путь до исполняемого файла PostgreSQL,
<DATA_DIR>
— путь до директории с данными кластера,
<CONFIG_PATH>
— пусть до конфигурационного файла postgresql.conf
(потребуется для дальнейшей диагностики).
В противном случае, проблема найдена: PostgreSQL не запущен.
Теперь необходимо убедиться, что PostgreSQL слушает нужный вам TCP-порт (если, конечно, вы не собираетесь работать только через Unix-сокеты).
Откройте конфигурационный файл postgresql.conf
(путь до него мы определили этапом выше) и найдите параметр port
.
Там должно быть значение необходимого вам порта, который по умолчанию равен 5432
.
В противном случае, исправьте номер порта на нужное вам значение. После применения изменений необходимо произвести рестарт PostgreSQL.
* В то же время, можно скорректировать значения порта непосредственно на клиенте (том самом, где возникла ошибка соединения) — всё зависит от конкретной цели, которую вы преследуете.
После рестарта PostgreSQL можно удостовериться, что нужный вам порт действительно прослушивается.
Для этого можно выполнить след. команду на сервере (для порта 5432
):
ss -ln | grep ":5432"
В случае успеха, в выводе команды вы должны наблюдать одну или несколько строк с операцией LISTEN, которые показывают, что PostgreSQL действительно прослушивает порт.
В противном случае (учитывая, что шаг выше показал, что основной процесс СУБД запущен),
вероятно, вы неверно указали значение port
либо настроена работа только через Unix-сокеты — как это исправить см. ниже.
Параметром в файле postgresql.conf
, отвечающим за то, через какие сетевые интерфейсы
PostgreSQL будет принимать соединения, является listen_addresses
.
Если вы хотите подключиться к PostgreSQL локально (т.е. с того же сервера), подойдут значения
127.0.0.1
(для подключения по IPv4), ::1
(для подключения по IPv6) или localhost
(в современных ОС данное доменное имя, как правило, транслируется в ::1
. Подробнее см. тут).
Стоит отметить, что в параметре listen_addresses
, как следует из его названия, можно указать несколько значений через запятую.
Учтите, что старые клиентские приложения, в подавляющем большинстве случаев, работают по IPv4.
Если вы хотите подключиться к PostgreSQL удаленно (т.е. с другого сервера), то необходимо принимать подключения с соотв. внешних интерфейсов.
С помощью значения 0.0.0.0
можно принимать подключения со всех адресов IPv4, а ::
— все адреса IPv6.
В то же время, если указать значение *
, то PostgreSQL будет принимать подключения со всех имеющихся сетевых интерфейсов.
Подробнее о подключениях и аутентификации к PostgreSQL см. тут.
Напомним, что после применения изменений в файл postgresql.conf
необходимо произвести рестарт PostgreSQL.
❗ В случае, если вы указали PostgreSQL прослушивать внешние интерфейсы
(т.е., что-то, отличное от значений 127.0.0.1
, ::1
или localhost
параметра listen_addresses
),
то ваш сервер может быть доступне извне (т.е. из Интернета) и потенциально находится под угрозой.
Чтобы избежать негативных последствий, необходимо корректно настроить ваш firewall и файл pg_hba.conf
. Подробнее о них см. ниже.
Несмотря на то, что параметр listen_addresses
в файле postgresql.conf
настроен верно, PostgreSQL всё ещё может отвергать соединения.
Причиной может быть то, что в конфигурационном файле pg_hba.conf
нет соответствующего разрешения.
Подробнее о файле pg_hba.conf
см. тут (включая примеры настройки).
Даже если PostgreSQL настроен верно (с точки зрения подключения клиентов), вы всё ещё можете иметь неудачные попытки подключения. В этом случае вам необходимо обратить внимание на правильность настройки firewall (он может быть как на уровне ОС, так и на уровне ваших сетевых аппаратных/виртуальных устройств, напр., роутера). Конкретные шаги выходят за рамки данного FAQ.
В подавляющем большинстве случаев, дело в том, что имя таблицы/колонки (равно как и любого другого символьного идентификатора) содержит символы в верхнем регистре (т.е. заглавные буквы). В то же время, по умолчанию, PostgreSQL преобразовывает указанные в запросе/команде идентификаторы в нижний регистр. Чтобы избежать ошибки, в запросе/команде необходимо заключить идентификатор в двойные кавычки (в этом случае вышеописанное преобразование будет отключено).
Пример воспроизведения и решения проблемы:
SELECT * FROM TableName; -- error: relation "tablename" does not exist
SELECT * FROM "TableName"; -- OK
Обратите внимание, что идентификатор TableName
без двойных кавычек был преобразован в tablename
, что вызвало ошибку.
Для того, чтобы даже гипотетически избежать таких проблем, не рекомендуется использование символов верхнего регистра в идентификаторах. Однако, это ни в коем случае не является обязательным правилом.
Прежде всего, не используйте скриншоты для того, чтобы показать SQL запросы (и/или их результаты), определения функций, выводы команд вспомогательных утилит (таких, как psql и др.) и прочую текстовую информацию. Заметно эффективнее будет публикация оных, напр., на gist или pastebin.com. Если вы задаете вопрос в tg-чате и кол-во содержимого невелико, его допускается опубликовать в режиме форматирования Monospace прямо в чат. Как правило, этот вопрос тесно связан с п. 2.4 и п. 2.5.
Многие участники сообщества принципиально не рассматривают скриншоты (и на это есть рациональные причины), поэтому постарайтесь оформить свой текст правильно.
Чтобы получить качественную помощь по оптимизации запроса и не уничтожить желание у сообщества помочь вам, необходимо немного постараться и собрать некоторые данные. Как в своё время метко подметил один уважаемый пользователь tg-чата, минимальная информация для получения помощи следующая:
EXPLAIN (ANALYZE, BUFFERS)
для запроса (подробнее об EXPLAIN см. тут).❗ Внимательно отнеситесь к тому, как публиковать информацию, которая требуется для ответа на ваш вопрос.
Подробнее о важных сведениях по существу вопроса см. тут.
❗ Внимательно отнеситесь к тому, как публиковать информацию, которая требуется для ответа на ваш вопрос.
Стоит отметить, что у сообщества нет единого мнения по данному вопросу. Единственный технический нюанс, который следует учитывать, описан выше. В остальном, это зависит исключительно от того, как принято в вашей команде и/или организации (т.н. code style). Внутри команды и/или организации важно соблюдать единый стандарт оформления кода для того чтобы в дальнейшем его было легко читать/поддерживать как вам, так и вашим коллегам.
Если обратиться к примерам официальной документации PostgreSQL (которые также имеют некоторое разночтение), то, как правило, им свойственно следующее:
SELECT * FROM table;
SELECT floor(col_name) FROM table;