18.3. Запуск сервера баз данных #

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

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

Самый прямолинейный вариант запуска сервера вручную — просто выполнить непосредственно postgres, указав расположение каталога данных в ключе -D, например:

$ postgres -D /usr/local/pgsql/data

В результате сервер продолжит работу на переднем плане. Запускать эту команду следует под именем учётной записи PostgreSQL. Без параметра -D сервер попытается использовать каталог данных, указанный в переменной окружения PGDATA. Если и эта переменная не определена, сервер не запустится.

Однако обычно лучше запускать postgres в фоновом режиме. Для этого можно применить обычный синтаксис, принятый в оболочке Unix:

$ postgres -D /usr/local/pgsql/data >logfile 2>&1 &

Важно где-либо сохранять информацию, которую выводит сервер в каналы stdout и stderr, как показано выше. Это полезно и для целей аудита, и для диагностики проблем. (Более глубоко работа с файлами журналов рассматривается в Разделе 24.3.)

Программа postgres также принимает несколько других параметров командной строки. За дополнительными сведениями обратитесь к справочной странице postgres и к следующей Главе 19.

Такой вариант запуска довольно быстро может оказаться неудобным. Поэтому для упрощения подобных задач предлагается вспомогательная программа pg_ctl. Например:

pg_ctl start -l logfile

запустит сервер в фоновом режиме и направит выводимые сообщения сервера в указанный файл журнала. Параметр -D для неё имеет то же значение, что и для программы postgres. С помощью pg_ctl также можно остановить сервер.

Обычно возникает желание, чтобы сервер баз данных сам запускался при загрузке операционной системы. Скрипты автозапуска для разных систем разные, но в составе PostgreSQL предлагается несколько типовых скриптов в каталоге contrib/start-scripts. Для установки такого скрипта в систему требуются права root.

В различных системах приняты разные соглашения о порядке запуска служб в процессе загрузки. Во многих системах для этого используется файл /etc/rc.local или /etc/rc.d/rc.local. В других применяются каталоги init.d или rc.d. Однако при любом варианте запускаться сервер должен от имени пользователя PostgreSQL, но не root или какого-либо другого пользователя. Поэтому команду запуска обычно следует записывать в форме su postgres -c '...'. Например:

su postgres -c 'pg_ctl start -D /usr/local/pgsql/data -l serverlog'

Ниже приведены более конкретные предложения для нескольких основных ОС. (Вместо указанных нами шаблонных значений необходимо подставить правильный путь к каталогу данных и фактическое имя пользователя.)

  • Для запуска во FreeBSD воспользуйтесь файлом contrib/start-scripts/freebsd в дереве исходного кода PostgreSQL.

  • В OpenBSD, добавьте в файл /etc/rc.local следующие строки:

    if [ -x /usr/local/pgsql/bin/pg_ctl -a -x /usr/local/pgsql/bin/postgres ]; then
        su -l postgres -c '/usr/local/pgsql/bin/pg_ctl start -s -l /var/postgresql/log -D /usr/local/pgsql/data'
        echo -n ' postgresql'
    fi
  • В системах Linux вы можете либо добавить

    /usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data

    в /etc/rc.d/rc.local или в /etc/rc.local, либо воспользоваться файлом contrib/start-scripts/linux в дереве исходного кода PostgreSQL.

    Используя systemd, вы можете применить следующий файл описания службы (например, /etc/systemd/system/postgresql.service):

    [Unit]
    Description=PostgreSQL database server
    Documentation=man:postgres(1)
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=notify
    User=postgres
    ExecStart=/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
    ExecReload=/bin/kill -HUP $MAINPID
    KillMode=mixed
    KillSignal=SIGINT
    TimeoutSec=infinity
    
    [Install]
    WantedBy=multi-user.target

    Для использования Type=notify требуется, чтобы сервер был скомпилирован с указанием configure --with-systemd.

    Особого внимания заслуживает значение тайм-аута. На момент написания этой документации по умолчанию в systemd принят тайм-аут 90 секунд, так что процесс, не сообщивший о своей готовности за это время, будет уничтожен. Но серверу PostgreSQL при запуске может потребоваться выполнить восстановление после сбоя, так что переход в состояние готовности может занять гораздо больше времени. Предлагаемое значение infinity отключает логику тайм-аута.

  • В NetBSD можно использовать скрипт запуска для FreeBSD или для Linux, в зависимости от предпочтений.

  • В Solaris, создайте файл с именем /etc/init.d/postgresql, содержащий следующую стоку:

    su - postgres -c "/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data"

    Затем создайте символическую ссылку на него в каталоге /etc/rc3.d с именем S99postgresql.

Когда сервер работает, идентификатор его процесса (PID) сохраняется в файле postmaster.pid в каталоге данных. Это позволяет исключить запуск нескольких экземпляров сервера с одним каталогом данных, а также может быть полезно для выключения сервера.

18.3.1. Сбои при запуске сервера #

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

LOG:  could not bind IPv4 address "127.0.0.1": Address already in use
HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
FATAL:  could not create any TCP/IP sockets

Это обычно означает именно то, что написано: вы пытаетесь запустить сервер на том же порту, на котором уже работает другой. Однако если сообщение ядра не Address already in use или подобное, возможна и другая проблема. Например, при попытке запустить сервер с номером зарезервированного порта будут выданы такие сообщения:

$ postgres -p 666
LOG:  could not bind IPv4 address "127.0.0.1": Permission denied
HINT:  Is another postmaster already running on port 666? If not, wait a few seconds and retry.
FATAL:  could not create any TCP/IP sockets

Следующее сообщение:

FATAL:  could not create shared memory segment: Invalid argument
DETAIL:  Failed system call was shmget(key=5440001, size=4011376640, 03600).

может означать, что установленный для вашего ядра предельный размер разделяемой памяти слишком мал для рабочей области, которую пытается создать PostgreSQL (в данном примере 4011376640 байт). Такая ситуация возможна, только если в shared_memory_type выбран вариант sysv. В этом случае можно попытаться запустить сервер с меньшим числом буферов (shared_buffers) или переконфигурировать ядро и увеличить допустимый размер разделяемой памяти. Вы также можете увидеть это сообщение при попытке запустить несколько серверов на одном компьютере, если запрошенный ими объём памяти в сумме превышает установленный в ядре предел.

Сообщение:

FATAL:  could not create semaphores: No space left on device
DETAIL:  Failed system call was semget(5440126, 17, 03600).

не означает, что у вас закончилось место на диске. Это значит, что установленное в вашем ядре предельное число семафоров System V меньше, чем количество семафоров, которое пытается создать PostgreSQL. Как и в предыдущем случае можно попытаться обойти эту проблему, запустив сервер с меньшим числом допустимых подключений (max_connections), но в конце концов вам придётся увеличить этот предел в ядре.

Настройка средств IPC в стиле System V описывается в Подразделе 18.4.1.

18.3.2. Проблемы с подключениями клиентов #

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

psql: ошибка: не удалось подключиться к серверу "server.joe.com" (123.123.123.123) по порту 5432: Connection refused
        Он действительно работает по адресу "server.joe.com" (123.123.123.123) и принимает TCP-соединения (порт 5432)?

Это общая проблема «я не могу найти сервер и начать взаимодействие с ним». Показанное выше сообщение говорит о попытке установить подключение по TCP/IP. Очень часто объясняется это тем, что сервер просто забыли настроить для работы по протоколу TCP/IP.

Кроме того, при попытке установить подключение к локальному серверу через Unix-сокет можно получить такое сообщение:

psql: ошибка: не удалось подключиться к серверу через сокет "/tmp/.s.PGSQL.5432": No such file or directory
        Он действительно работает локально и принимает соединения через этот сокет?

Если сервер действительно работает, проверьте, что указываемый клиентом путь сокета (здесь /tmp) соответствует значению unix_socket_directories.

Сообщение об ошибке подключения всегда содержит адрес сервера или путь к сокету, что помогает понять, куда именно подключается клиент. Если сервер на самом деле не принимает подключения по этому адресу, обычно выдаётся сообщение ядра Connection refused (В соединении отказано) или No such file or directory (Нет такого файла или каталога), приведённое выше. (Важно понимать, что Connection refused в данном контексте не означает, что сервер получил запрос на подключение и отверг его. В этом случае были бы выданы другие сообщения, например, показанные в Разделе 20.15.) Другие сообщения об ошибках, например Connection timed out (Тайм-аут соединения) могут сигнализировать о более фундаментальных проблемах, например, о нарушениях сетевых соединений или о блокировании подключения брандмауэром.