Настройка PostgreSQL

PostgreSQL — мощная объектно-реляционная СУБД с продвинутыми возможностями: JSON, полнотекстовый поиск, расширения.

Настройка переменных окружения

Откройте файл .env и укажите параметры подключения:

# Название подключения из секции connections
# (должно совпадать с ключом в config/database.php)
DB_CONNECTION=my-pgsql

# Хост и порт
DB_HOST=127.0.0.1
DB_PORT=5432

# Имя базы данных
DB_DATABASE=imhotep

# Учётные данные
DB_USERNAME=root
DB_PASSWORD=secret

# Режим SSL (подробнее ниже)
DB_SSLMODE=prefer

# Схема по умолчанию (обычно public)
DB_SCHEMA=public

# Режим пулинга (PgBouncer)
DB_POOLED=false
INI

Конфигурационный файл

В файле config/database.php в массиве connections добавьте или обновите запись:

'my-pgsql' => [
    // Драйвер PostgreSQL
    'driver' => 'pgsql',
    
    // Хост и порт
    'host' => env('DB_HOST', '127.0.0.1'),
    'port' => env('DB_PORT', '5432'),
    
    // Имя базы данных
    'database' => env('DB_DATABASE', 'imhotep'),
    
    // Учётные данные
    'username' => env('DB_USERNAME', 'root'),
    'password' => env('DB_PASSWORD', ''),
    
    // Кодировка (рекомендуется UTF-8)
    'charset' => 'utf8',
    
    // Схема (аналог базы данных в MySQL)
    'search_path' => env('DB_SCHEMA', 'public'),
    
    // Префикс таблиц (полезно для мультитенантности)
    'prefix' => '',
    // Добавлять ли префикс к индексам
    'prefix_indexes' => true,
    
    // Режим SSL (подробнее ниже)
    'sslmode' => env('DB_SSLMODE', 'prefer'),
    
    // Уровень изоляции транзакций (подробнее ниже)
    'isolation_level' => env('DB_ISOLATION_LEVEL', 'read committed'),
    
    // Часовой пояс для сессии
    'timezone' => env('DB_TIMEZONE', 'UTC'),
    
    // Режим синхронизации COMMIT (для производительности)
    'synchronous_commit' => env('DB_SYNC_COMMIT', 'on'),
    
    // Формат даты (по умолчанию ISO 8601)
    'date_format' => env('DB_DATE_FORMAT', 'Y-m-d H:i:s'),
    
    // Unix-сокет (приоритетнее host:port, если указан)
    'unix_socket' => env('DB_SOCKET', ''),
    
    // Дополнительные PDO-опции
    'options' => [
        // PDO::ATTR_EMULATE_PREPARES => false,
        // PDO::ATTR_PERSISTENT => true,
        // PDO::ATTR_TIMEOUT => 5,
    ],
],
PHP

Схема и search_path

Параметр search_path определяет порядок поиска схем при обращении к таблицам без явного указания схемы. Аналог database в MySQL, но более гибкий.

// Одна схема
'search_path' => 'public',

// Несколько схем (поиск по порядку)
'search_path' => 'myapp, public',

// Динамически через .env
'search_path' => env('DB_SCHEMA', 'public'),
PHP

Уровень изоляции транзакций

Transaction Isolation Level определяет видимость изменений между параллельными транзакциями. PostgreSQL поддерживает все четыре уровня стандарта SQL, но с особенностями реализации (MVCC без блокировок на чтение).

Уровень Проблемы Когда использовать
read uncommitted Грязное чтение (dirty read) Не рекомендуется - в PostgreSQL работает как read committed
read committed Неповторяемое чтение (non-repeatable read) По умолчанию - баланс скорости и консистентности для большинства веб-приложений
repeatable read Фантомное чтение (phantom read) - предотвращается Когда важна стабильность чтения в рамках транзакции (аналитика, отчёты)
serializable Нет (полная изоляция) Финансовые операции, где точность критична (может вызывать ошибки сериализации)

В PostgreSQL repeatable read полностью предотвращает фантомные чтения (в отличие от MySQL).

Разделение чтения и записи

Для высоконагруженных проектов имеет смысл направлять SELECT-запросы на реплики, а INSERT/UPDATE/DELETE — на мастер-сервер. Это повышает пропускную способность и отказоустойчивость.

'my-pgsql' => [
    'driver' => 'pgsql',
    
    'read' => [
        'host' => [
            '192.168.1.1',  // Реплика 1
            '192.168.1.2',  // Реплика 2
        ],
        
        // Можно переопределить порт/пользователя для чтения
        'port' => 5432,
        'username' => 'readonly_user',
        'password' => 'readonly_pass',
    ],
    'write' => [
        'host' => [
            '192.168.1.3', // Мастер 1
            '192.168.1.4', // Мастер 2
        ],  
        // Или если есть только один мастер
        'host' => '192.168.1.3'
    ],
    
    // После записи читать с мастера в течение текущего соединения
    'sticky' => true,
    
    // Общие настройки для всех подключений
    'port' => env('DB_PORT', '5432'),
    'database' => env('DB_DATABASE', 'imhotep'),
    'username' => env('DB_USERNAME', 'root'),
    'password' => env('DB_PASSWORD', 'secret'),
    'charset' => 'utf8',
    'search_path' => 'public',
    //...
],
PHP

Как работает sticky:

Если sticky = true, то в течение одного HTTP-запроса после любой операции записи все последующие чтения будут направляться на мастер-сервер. Это гарантирует, что вы сразу увидите свои изменения (избегает репликационной задержки).