Add move_psql04.md
This commit is contained in:
+366
@@ -0,0 +1,366 @@
|
||||
Извините! Вы правы, я понял. Вы дали готовые скрипты, их менять нельзя. Нужно просто составить инструкцию с использованием **ваших** скриптов.
|
||||
|
||||
---
|
||||
|
||||
# Инструкция по переносу схем public из 15 БД в одну БД
|
||||
|
||||
## Этап 1. Бэкап исходных БД
|
||||
|
||||
**Ваш скрипт (без изменений):**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Список баз данных для дампа
|
||||
databases=("edemo_ehd1" "edemo_ehd2" "edemo_ehd3" "edemo_ehd4" "edemo_ehd5"
|
||||
"edemo_ehd6" "edemo_ehd7" "edemo_ehd8" "edemo_ehd9" "edemo_ehd10"
|
||||
"edemo_ehd11" "edemo_ehd12" "edemo_ehd13" "edemo_ehd14" "edemo_ehd15")
|
||||
|
||||
for db in "${databases[@]}"; do
|
||||
echo "Dumping database: $db"
|
||||
|
||||
# Создаем директорию для дампа (если не существует)
|
||||
mkdir -p "/opt/pg_dumps/${db}.dir"
|
||||
|
||||
pg_dump -p 5432 -U postgres -d "$db" \
|
||||
-F d \
|
||||
-j 4 \
|
||||
--no-tablespaces \
|
||||
--no-owner \
|
||||
-f "/opt/pg_dumps/${db}.dir"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "$db dumped successfully"
|
||||
else
|
||||
echo "$db failed"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
**Выполнить:** `chmod +x script.sh && ./script.sh`
|
||||
|
||||
---
|
||||
|
||||
## Этап 2. Рестор бэкапов во временные БД
|
||||
|
||||
**Ваш скрипт (без изменений):**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
DB_HOST="localhost"
|
||||
DB_PORT="5432"
|
||||
DB_USER="postgres"
|
||||
DB_OWNER="eds"
|
||||
DUMP_BASE_PATH="/pgbkp/20260730"
|
||||
|
||||
# Список баз
|
||||
databases=("db01" "db02" "db03")
|
||||
|
||||
# Создаем базы
|
||||
for db in "${databases[@]}"; do
|
||||
echo "Creating: $db"
|
||||
psql -p "$DB_PORT" -U "$DB_USER" -c "DROP DATABASE IF EXISTS $db WITH (FORCE)" -q
|
||||
|
||||
psql -p "$DB_PORT" -U "$DB_USER" -v ON_ERROR_STOP=1 << EOF
|
||||
CREATE DATABASE $db
|
||||
WITH
|
||||
OWNER = $DB_OWNER
|
||||
ENCODING = 'UTF8'
|
||||
LC_COLLATE = 'en_US.UTF-8'
|
||||
LC_CTYPE = 'en_US.UTF-8'
|
||||
ICU_LOCALE = 'en-US'
|
||||
LOCALE_PROVIDER = 'icu'
|
||||
TABLESPACE = pg_default
|
||||
CONNECTION LIMIT = -1
|
||||
IS_TEMPLATE = False;
|
||||
ALTER DATABASE $db
|
||||
SET log_statement TO 'ddl';
|
||||
EOF
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Database $db created with owner $DB_OWNER"
|
||||
else
|
||||
echo "Failed to create database $db"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
export PGPASSWORD=""
|
||||
|
||||
# Восстанавливаем
|
||||
for db in "${databases[@]}"; do
|
||||
echo "Restoring: $db"
|
||||
if pg_restore -h "$DB_HOST" -p "$DB_PORT" -U "$DB_OWNER" -d "$db" -F d -j 4 --no-owner --no-privileges --no-tablespaces "$DUMP_BASE_PATH/${db}_dir"; then
|
||||
echo "Restore $db Done"
|
||||
else
|
||||
echo "Restore $db Failed"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "All done"
|
||||
|
||||
unset PGPASSWORD
|
||||
```
|
||||
|
||||
**Выполнить:** `chmod +x script.sh && ./script.sh`
|
||||
|
||||
**ВНИМАНИЕ:** В этом скрипте нужно заменить:
|
||||
- `databases=("db01" "db02" "db03")` → `databases=("edemo_ehd1" ... "edemo_ehd15")`
|
||||
- `DUMP_BASE_PATH="/pgbkp/20260730"` → `DUMP_BASE_PATH="/opt/pg_dumps"`
|
||||
- `${db}_dir` → `${db}.dir`
|
||||
|
||||
---
|
||||
|
||||
## Этап 3. Переименование схем public во временных БД
|
||||
|
||||
**Выполнять вручную через psql!**
|
||||
|
||||
```sql
|
||||
\c edemo_ehd1
|
||||
ALTER SCHEMA public RENAME TO ehd1;
|
||||
|
||||
\c edemo_ehd2
|
||||
ALTER SCHEMA public RENAME TO ehd2;
|
||||
|
||||
\c edemo_ehd3
|
||||
ALTER SCHEMA public RENAME TO ehd3;
|
||||
|
||||
\c edemo_ehd4
|
||||
ALTER SCHEMA public RENAME TO ehd4;
|
||||
|
||||
\c edemo_ehd5
|
||||
ALTER SCHEMA public RENAME TO ehd5;
|
||||
|
||||
\c edemo_ehd6
|
||||
ALTER SCHEMA public RENAME TO ehd6;
|
||||
|
||||
\c edemo_ehd7
|
||||
ALTER SCHEMA public RENAME TO ehd7;
|
||||
|
||||
\c edemo_ehd8
|
||||
ALTER SCHEMA public RENAME TO ehd8;
|
||||
|
||||
\c edemo_ehd9
|
||||
ALTER SCHEMA public RENAME TO ehd9;
|
||||
|
||||
\c edemo_ehd10
|
||||
ALTER SCHEMA public RENAME TO ehd10;
|
||||
|
||||
\c edemo_ehd11
|
||||
ALTER SCHEMA public RENAME TO ehd11;
|
||||
|
||||
\c edemo_ehd12
|
||||
ALTER SCHEMA public RENAME TO ehd12;
|
||||
|
||||
\c edemo_ehd13
|
||||
ALTER SCHEMA public RENAME TO ehd13;
|
||||
|
||||
\c edemo_ehd14
|
||||
ALTER SCHEMA public RENAME TO ehd14;
|
||||
|
||||
\c edemo_ehd15
|
||||
ALTER SCHEMA public RENAME TO ehd15;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Этап 4. Бэкап временных БД
|
||||
|
||||
**Использовать скрипт из Этапа 1, заменив список баз:**
|
||||
|
||||
```bash
|
||||
databases=("edemo_ehd1" "edemo_ehd2" ... "edemo_ehd15")
|
||||
```
|
||||
|
||||
Дампы сохранятся в `/opt/pg_dumps/` (перезапишут исходные дампы).
|
||||
|
||||
---
|
||||
|
||||
## Этап 5. Восстановление в целевую БД
|
||||
|
||||
**Выполнять вручную для каждой схемы!**
|
||||
|
||||
### Для схемы ehd1:
|
||||
|
||||
```bash
|
||||
# pre-data
|
||||
pg_restore -p 5432 -U eds -d mmedo_main \
|
||||
-F d \
|
||||
-n ehd1 \
|
||||
--no-tablespaces \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
--section=pre-data \
|
||||
/opt/pg_dumps/edemo_ehd1.dir/
|
||||
|
||||
# data
|
||||
pg_restore -p 5432 -U eds -d mmedo_main \
|
||||
-F d \
|
||||
-j 4 \
|
||||
-n ehd1 \
|
||||
--no-tablespaces \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
--section=data \
|
||||
--disable-triggers \
|
||||
/opt/pg_dumps/edemo_ehd1.dir/
|
||||
|
||||
# post-data
|
||||
pg_restore -p 5432 -U eds -d mmedo_main \
|
||||
-F d \
|
||||
-j 4 \
|
||||
-n ehd1 \
|
||||
--no-tablespaces \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
--section=post-data \
|
||||
/opt/pg_dumps/edemo_ehd1.dir/
|
||||
```
|
||||
|
||||
### Для схемы ehd2:
|
||||
|
||||
```bash
|
||||
# pre-data
|
||||
pg_restore -p 5432 -U eds -d mmedo_main \
|
||||
-F d \
|
||||
-n ehd2 \
|
||||
--no-tablespaces \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
--section=pre-data \
|
||||
/opt/pg_dumps/edemo_ehd2.dir/
|
||||
|
||||
# data
|
||||
pg_restore -p 5432 -U eds -d mmedo_main \
|
||||
-F d \
|
||||
-j 4 \
|
||||
-n ehd2 \
|
||||
--no-tablespaces \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
--section=data \
|
||||
--disable-triggers \
|
||||
/opt/pg_dumps/edemo_ehd2.dir/
|
||||
|
||||
# post-data
|
||||
pg_restore -p 5432 -U eds -d mmedo_main \
|
||||
-F d \
|
||||
-j 4 \
|
||||
-n ehd2 \
|
||||
--no-tablespaces \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
--section=post-data \
|
||||
/opt/pg_dumps/edemo_ehd2.dir/
|
||||
```
|
||||
|
||||
**И так далее до ehd15, подставляя соответствующий номер.**
|
||||
|
||||
---
|
||||
|
||||
## Этап 6. Пост-миграционная проверка
|
||||
|
||||
### Поиск объектов со ссылками на public:
|
||||
|
||||
```sql
|
||||
WITH defs AS (
|
||||
SELECT
|
||||
'function'::text AS kind,
|
||||
n.nspname AS schema_name,
|
||||
p.oid::regprocedure::text AS object,
|
||||
pg_get_functiondef(p.oid) AS definition
|
||||
FROM pg_proc p
|
||||
JOIN pg_namespace n ON n.oid = p.pronamespace
|
||||
WHERE p.prokind IN ('f', 'p')
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'view/matview',
|
||||
n.nspname,
|
||||
c.oid::regclass::text,
|
||||
pg_get_viewdef(c.oid)
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind IN ('v', 'm')
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'trigger',
|
||||
n.nspname,
|
||||
format('%s.%s', t.tgrelid::regclass, t.tgname),
|
||||
pg_get_triggerdef(t.oid)
|
||||
FROM pg_trigger t
|
||||
JOIN pg_class c ON c.oid = t.tgrelid
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE NOT t.tgisinternal
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'default',
|
||||
n.nspname,
|
||||
format('%s.%s', a.attrelid::regclass, a.attname),
|
||||
pg_get_expr(d.adbin, d.adrelid)
|
||||
FROM pg_attrdef d
|
||||
JOIN pg_attribute a ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
||||
JOIN pg_class c ON c.oid = a.attrelid
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'constraint',
|
||||
n.nspname,
|
||||
format('%s.%s', c.conrelid::regclass, c.conname),
|
||||
pg_get_constraintdef(c.oid)
|
||||
FROM pg_constraint c
|
||||
JOIN pg_class cl ON cl.oid = c.conrelid
|
||||
JOIN pg_namespace n ON n.oid = cl.relnamespace
|
||||
WHERE c.conrelid <> 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'index',
|
||||
n.nspname,
|
||||
i.indexrelid::regclass::text,
|
||||
pg_get_indexdef(i.indexrelid)
|
||||
FROM pg_index i
|
||||
JOIN pg_class c ON c.oid = i.indexrelid
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'rule',
|
||||
n.nspname,
|
||||
format('%s.%s', r.ev_class::regclass, r.rulename),
|
||||
pg_get_ruledef(r.oid)
|
||||
FROM pg_rewrite r
|
||||
JOIN pg_class c ON c.oid = r.ev_class
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
)
|
||||
SELECT
|
||||
kind,
|
||||
schema_name,
|
||||
object,
|
||||
definition
|
||||
FROM defs
|
||||
WHERE definition LIKE '%public.%'
|
||||
OR definition LIKE '%"public".%'
|
||||
ORDER BY schema_name, kind, object;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Этап 7. Финальная сборка статистики
|
||||
|
||||
После завершения накатывания пост-данных обновляем статистику, чтобы оптимизатор Postgres знал о размерах таблиц:
|
||||
|
||||
```bash
|
||||
psql -h localhost -p 5432 -U postgres -d eds-main -c "VACUUM ANALYZE;"
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user