Files
psql_tasks/move_psql02.md
T
2026-07-21 00:51:54 +08:00

162 lines
7.4 KiB
Markdown

Главная причина всех ваших ошибок при заливке данных — **включённые триггеры и внешние ключи (Foreign Keys)** в момент выполнения `COPY`.
Из логов видно:
1. Таблицы заполняются параллельно или в произвольном порядке.
2. Срабатывает триггер (например, `TrgAddBarcodePairOnInsert`), который пытается делать `INSERT` в таблицу `BarcodeOldBarcodePair`, **до того** как сама эта таблица успела создаться или заполниться.
3. Триггеры вызывают функции, которые начинают параллельно обновлять одну и ту же справочную таблицу (в логе — `AccessGroupModels`), что приводит к **взаимным блокировкам (deadlock)**.
4. Включаются Foreign Key проверки до того, как загрузились родительские таблицы.
Делить дамп на 10 отдельных файлов (отдельно функции, отдельно вьюхи) не требуется. Достаточно строго разделить процесс на **3 фазы**: **Схема без ключей/триггеров $\rightarrow$ Данные (с отключенными триггерами) $\rightarrow$ Индексы, ключи, триггеры и вьюхи.**
Инструменты `pg_dump` и `pg_restore` в кастомном формате (`-Fc`) умеют делать это идеально с помощью **файла оглавления (List File)**.
---
## Подготовка: Как заменить Tablespace
Чтобы не фильтровать SQL через `sed`/`grep`, передавайте флаг `--no-tablespaces` в `pg_dump`.
Если хотите сменить владельца объектов на того, кто восстанавливает дамп, используйте флаг `--no-owner`.
---
## Этап 1. Создание дампов на `dc01-srv01`
Делаем один полноценный дамп в кастомном бинарном формате (`-Fc`). Это даст нам гибкость при восстановлении — мы сможем восстанавливать объекты в любом порядке.
### Шаг 1.1. Создаём полный дамп схемы и данных
```bash
pg_dump -h localhost -p 5436 -U postgres -d edemo_ehd1 \
-F c \
--no-tablespaces \
--no-owner \
-f /opt/pg_dumps/edemo_ehd1_full.dump
```
### Шаг 1.2. Генерируем файл оглавления (List file)
Этот файл содержит полный список всех создаваемых объектов (таблицы, функции, индексы, FK, триггеры). На его основе мы разделим восстановление на этапы.
```bash
pg_restore -l /opt/pg_dumps/edemo_ehd1_full.dump > /opt/pg_dumps/db.list
```
### Шаг 1.3. Разделяем `db.list` на 3 части
Сделайте 3 копии файла `db.list`:
```bash
cp /opt/pg_dumps/db.list /opt/pg_dumps/step1_pre_data.list
cp /opt/pg_dumps/db.list /opt/pg_dumps/step2_data.list
cp /opt/pg_dumps/db.list /opt/pg_dumps/step3_post_data.list
```
Отредактируйте эти файлы текстовым редактором (`nano` или `vim`):
1. **`step1_pre_data.list`** — Оставьте только:
* `SCHEMA`, `EXTENSION`, `TYPE`, `SEQUENCE`
* `TABLE` (структуру)
* `FUNCTION` / `PROCEDURE` (они нужны, если столбцы используют дефолтные значения из функций)
* *Удалите или закомментируйте (знаком `;` в начале строки) все строки с `TABLE DATA`, `CONSTRAINT`, `FOREIGN KEY`, `INDEX`, `TRIGGER`, `VIEW`, `MATERIALIZED VIEW`.*
2. **`step2_data.list`** — Оставьте только:
* Строки вида `TABLE DATA` (само наполнение).
* *Всё остальное удалите или закомментируйте.*
3. **`step3_post_data.list`** — Оставьте всё, что создается **после** заливки данных:
* `PRIMARY KEY`, `UNIQUE`, `CONSTRAINT`, `FOREIGN KEY`
* `INDEX`
* `TRIGGER`
* `VIEW` и `MATERIALIZED VIEW`
* `RULE`
* *Удалите строки `TABLE DATA`, базовые `TABLE` и `SCHEMA`.*
---
## Этап 2. Восстановление на `dc02-srv02`
Перенесите файл дампа `edemo_ehd1_full.dump` и 3 созданных `.list` файла на целевой сервер.
Убедитесь, что базовая БД создана на целевом сервере:
```sql
CREATE DATABASE edemo_ehd1;
```
---
### Шаг 2.1. Создаём структуру (Pre-Data)
На этом этапе создаются только таблицы, типы и функции. Нет ни триггеров, ни внешних ключей.
```bash
pg_restore -h localhost -p 5432 -U postgres -d edemo_ehd1 \
--no-tablespaces \
--no-owner \
-L /opt/pg_dumps/step1_pre_data.list \
/opt/pg_dumps/edemo_ehd1_full.dump
```
---
### Шаг 2.2. Загружаем данные (Data)
Самый критичный момент: используем параметр `--disable-triggers`. Он отключает срабатывание триггеров во время выполнения `COPY`, что полностью убирает ваши ошибки `deadlock` и ошибки отсутствия записей в смежных таблицах.
> **Важно:** Флаг `--disable-triggers` работает только если восстановление идет от имени суперпользователя (`postgres`).
```bash
pg_restore -h localhost -p 5432 -U postgres -d edemo_ehd1 \
--no-tablespaces \
--no-owner \
--disable-triggers \
-j 4 \
-L /opt/pg_dumps/step2_data.list \
/opt/pg_dumps/edemo_ehd1_full.dump
```
*(Параметр `-j 4` запустит параллельную загрузку в 4 потока для ускорения. Так как триггеры и FK отключены, таблицы загружаются без дедлоков).*
---
### Шаг 2.3. Создаём индексы, внешние ключи, триггеры и вьюхи (Post-Data)
Теперь, когда все данные уже на месте, PostgreSQL построит индексы, навесит Foreign Key и включает триггеры для новых операций.
```bash
pg_restore -h localhost -p 5432 -U postgres -d edemo_ehd1 \
--no-tablespaces \
--no-owner \
-j 4 \
-L /opt/pg_dumps/step3_post_data.list \
/opt/pg_dumps/edemo_ehd1_full.dump
```
*(Параметр `-j 4` здесь значительно ускорит построение индексов).*
---
### Шаг 2.4. Финальный шаг (Анализ БД)
После завершения восстановления обязательно обновите статистику планировщика запросов:
```bash
psql -h localhost -p 5432 -U postgres -d edemo_ehd1 -c "VACUUM ANALYZE;"
```