getpgdata: подробная документация переноса данных в новую БД (history + data/README)
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
# data/ — дамп данных прежней БД
|
||||
|
||||
Здесь сохранены данные, выгруженные из **прежней** PostgreSQL (инстанс
|
||||
`postgresqlk8s-master.60bdf3e3-...`, БД `ipwhitelist`), до переноса в новую
|
||||
(инстанс `a5e9d24f`).
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Таблица | Строк | Описание |
|
||||
|---|---|---|---|
|
||||
| `companies.json` | companies | 9 | метаданные компаний (id, client_id, name, custom_limit, created_at, updated_at) |
|
||||
| `whitelist_entries.json` | whitelist_entries | 20 | записи белого списка (IP, comment, кто создал/изменил/удалил, даты) |
|
||||
| `audit_log.json` | audit_log | 39 | журнал аудита (user_email, company_id, action, old/new_value, entry_id, created_at) |
|
||||
| `_migrations.json` | _migrations | 2 | применённые миграции |
|
||||
| `import.sql` | — | 84 строки | готовый SQL-скрипт вставки (companies → entries → audit + sequence) |
|
||||
|
||||
Формат каждого `.json` — ответ `POST /api/sql`:
|
||||
```json
|
||||
{ "ok": true, "fields": [...], "rows": [...], "rowCount": N }
|
||||
```
|
||||
|
||||
## Почему нет session.json
|
||||
|
||||
Таблица `session` (1147 строк) — временные пользовательские сессии входа
|
||||
(`connect-pg-simple`). Для переноса белых списков не нужна и не переносится —
|
||||
в новой БД сессии создаются заново. Дамп `session.json` был обрезан и удалён.
|
||||
|
||||
## import.sql
|
||||
|
||||
Генерируется из `*.json` и содержит:
|
||||
- `BEGIN; ... COMMIT;` — транзакция
|
||||
- INSERT для `companies` (с явными id, `ON CONFLICT (id) DO NOTHING`)
|
||||
- INSERT для `whitelist_entries` (id + company_id — ссылки сохранены)
|
||||
- INSERT для `audit_log`
|
||||
- `SELECT setval(...)` — сброс sequence на MAX(id)
|
||||
|
||||
**Важно:** `/api/sql` выполняет ОДИН statement за вызов, поэтому `import.sql` целиком
|
||||
никак не выполнить одним запросом. Вставка делалась клиентом по одному INSERT.
|
||||
@@ -141,3 +141,103 @@ PostgreSQL (тот же realm k8s). Доступ к новой БД — чере
|
||||
**Проверено:** `node -c server.js` OK; локально: пустой SQL → 400; SELECT → идёт в БД;
|
||||
`INSERT` без `WRITE_SQL` → 403 (до попытки подключения); `WRITE_SQL=1` + мульти-statement →
|
||||
берётся только первый; процесс проверки остановлен.
|
||||
|
||||
## 8. Перенос данных из прежней БД в новую (60bdf3e3 → a5e9d24f)
|
||||
|
||||
**Цель:** перенести белые списки (IP, кто создал, когда) и связанные данные в **новую**
|
||||
PostgreSQL (инстанс `a5e9d24f`), тот же realm k8s. Доступ к новой БД — через Keycloak,
|
||||
автоматизировать нельзя → перенос выполнен через `getpgdata` + `POST /api/sql`.
|
||||
|
||||
### 8.1 Выгрузка данных из прежней БД
|
||||
|
||||
Пока приложение было подключено к прежней БД (`60bdf3e3`), все таблицы выгружены через
|
||||
`/api/sql` (SELECT * ORDER BY id) и **сохранены в репо** в `data/*.json`:
|
||||
|
||||
| Файл | Таблица | Строк | Статус |
|
||||
|---|---|---|---|
|
||||
| `data/companies.json` | companies | 9 | полный, валиден |
|
||||
| `data/whitelist_entries.json` | whitelist_entries | 20 | полный, валиден |
|
||||
| `data/audit_log.json` | audit_log | 39 | полный, валиден |
|
||||
| `data/_migrations.json` | _migrations | 2 | полный, валиден |
|
||||
| session | session | 1147 | исключён (битый дамп, не нужен для переноса) |
|
||||
|
||||
Сессии намеренно НЕ переносятся: это временные пользовательские сессии входа
|
||||
(`connect-pg-simple`), в новой БД они создаются заново.
|
||||
|
||||
Коммиты: данные `~`, генератор `data/import.sql` (коммит `0b2d7ac`).
|
||||
|
||||
⚠️ **Урок (зафиксирован в памяти):** нужно было выгрузить ВСЕ таблицы до смены кредов.
|
||||
Первая выгрузка сохранила только `whitelist_entries`; `companies`/`audit_log` пришлось
|
||||
догонять после временного возврата кредов на прежнюю БД.
|
||||
|
||||
### 8.2 Переключение на новую БД
|
||||
|
||||
В jsonEnv Nubes (`modify`) заданы креды новой ПГ + `WRITE_SQL=1`:
|
||||
```json
|
||||
{
|
||||
"DB_HOST": "postgresqlk8s-master.a5e9d24f-0b5d-4196-8903-7ed60f6e6557.svc.cluster.local",
|
||||
"DB_PORT": "5432",
|
||||
"DB_NAME": "ipwhitelist",
|
||||
"DB_USER": "super",
|
||||
"DB_PASS": "<пароль новой ПГ>",
|
||||
"DB_SSLMODE": "disable",
|
||||
"WRITE_SQL": "1",
|
||||
"PORT": "3000"
|
||||
}
|
||||
```
|
||||
После `modify` проверено: `GET /` показывает host новой ПГ; `CREATE TEMP TABLE` → 200
|
||||
(запись разрешена).
|
||||
|
||||
### 8.3 Проблема: несоответствие id компаний
|
||||
|
||||
В новой БД **изначально уже были компании** под другими id (типовая схема), поэтому при
|
||||
прямой вставке по старым id возникли конфликты:
|
||||
|
||||
- Вставка с явным id: `WZ03709`(id=23) упал — duplicate key по `client_id` (в новой БД
|
||||
`WZ03709` уже был под id=2)
|
||||
- `WZ01112` и `WZ03709` оказались на неверных id (1 и 2 вместо 2 и 23)
|
||||
- `WZ01325` (должен быть id=1) — вообще отсутствовал
|
||||
|
||||
**Причина:** уникальный индекс `companies_client_id_key` (client_id), id в новой БД не
|
||||
совпадали со старой.
|
||||
|
||||
**Решение (безопасно, т.к. записи/аудит в новой БД были пусты и FK на companies отсутствуют):**
|
||||
1. `DELETE FROM companies WHERE client_id IN ('WZ01112','WZ03709')` — убрать с неверных id
|
||||
2. Вставить заново под правильные id: id=1→WZ01325, id=2→WZ01112, id=23→WZ03709
|
||||
3. Восстановить `custom_limit` и даты для этих 3 строк из дампа (первая вставка ставила `NOW()`)
|
||||
|
||||
После этого маппинг id компаний новой БД **полностью совпал** со старой.
|
||||
|
||||
### 8.4 Вставка данных через /api/sql
|
||||
|
||||
Так как `/api/sql` выполняет **один statement** за вызов, INSERT отправлены по одному
|
||||
стейтменту (клиент на Python):
|
||||
|
||||
1. `companies` — 9 вставок (с явными id, `ON CONFLICT (id) DO NOTHING`)
|
||||
2. `whitelist_entries` — 20 вставок (id, company_id, value_cidr, comment, created_by,
|
||||
created_at, updated_by, updated_at, deleted_by, deleted_at)
|
||||
3. `audit_log` — 39 вставок
|
||||
4. `SELECT setval(...)` — сброс sequence для трёх таблиц на MAX(id)
|
||||
|
||||
### 8.5 Проверка целостности и соответствия
|
||||
|
||||
После переноса выполнена **посимвольная сверка** новой БД против дампа старой:
|
||||
|
||||
| Таблица | Строк old/new | missing | extra | diffs | Результат |
|
||||
|---|---|---|---|---|---|
|
||||
| whitelist_entries | 20/20 | 0 | 0 | 0 | **MATCH** |
|
||||
| audit_log | 39/39 | 0 | 0 | 0 | **MATCH** |
|
||||
| companies | 9/9 | 0 | 0 | 0 (после фикса) | **MATCH** |
|
||||
|
||||
- `orphan` (записи без компании): **0** — все связи верны
|
||||
- sequences: companies→368, whitelist_entries→20, audit_log→39
|
||||
|
||||
### 8.6 Итоговое состояние новой БД
|
||||
|
||||
- companies = 9
|
||||
- whitelist_entries = 20 (из них активных 12, удалённых 8 — перенесены с deleted_at)
|
||||
- audit_log = 39
|
||||
- Данные идентичны прежней БД.
|
||||
|
||||
**Активные белые списки (12):** WZ02425 (2), WZ02727 (6), WZ03656 (2), WZ01112 (8.8.8.8).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user