wiki/docs/postgresql/Разное.md
ilyamak04 14df819a9e
All checks were successful
Build MkDocs / build-and-deploy (push) Successful in 20s
+
2025-03-08 12:29:25 +03:00

456 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### Полезные ссылки
[Cheat sheet](https://gist.github.com/Kartones/dd3ff5ec5ea238d4c546)
### Команды
- `sudo -u postgres psql postgres` - подключиться к базе данных `postgres` от имени пользователя Linux `postgres`
!!! tip ""
`sudo -u postgres psql`
Если не указано имя базы данных при подключении, `psql` попытается подключиться к базе данных с именем, совпадающим с именем пользователя. В данном случае это будет база данных postgres
- `sudo -u postgres psql -d имя_базы_данных -f путь_к_скрипту.sql` - выполнить SQL-скрипт на базе
- `sudo -u postgres psql -d имя_базы_данных -c "SQL-запрос"` - выполнить SQL-скрипт на базе
!!! tip "Команды `psql` начинаются с `\`"
- `\l` - просмотр списка БД
- `\du` - посмотреть какие роли назначены пользователю
- `\q` - выход из psql
- `\e` - открывает текстовый редактор для написания SQL-запроса
- `\c <database_name> <user_name>` - подключение к БД или из bash `psql -U username -d <database_name>`
- `\dt` - просмотр списка таблиц
- `\d <table_name>` - показывает столбцы, типы данных и индексы
- `\dn` - список схем
- `\dt <schema_name>` - список таблиц в схеме
- `psql -U postgres -d my_database -f /etc/script.sql` - выполнить скрипт
---
- `CREATE TABLE имя_таблицы (id SERIAL PRIMARY KEY, колонка1 тип, колонка2 тип, ...);` - создание таблицы
- `CREATE USER имя_пользователя WITH PASSWORD 'пароль';`
- `CREATE ROLE имя_роли;`
??? info "В чём разница USER и ROLE?"
Пользователь (USER) — это роль, которая по умолчанию ИМЕЕТ право на подключение к базе данных
Роль (ROLE) — это более общее понятие. Она может быть как пользователем, так и группой. Роль по умолчанию НЕ ИМЕЕТ права на подключение к базе данных (если не указан атрибут LOGIN)
Роли (и пользователи) могут иметь дополнительные атрибуты, которые определяют их поведение. Вот основные атрибуты:
- `LOGIN` - Позволяет роли подключаться к базе данных (по умолчанию для USER)
- `SUPERUSER` - Дает роли права суперпользователя
- `CREATEDB` - Позволяет роли создавать базы данных
- `CREATEROLE` - Позволяет роли создавать другие роли
- `INHERIT` - Позволяет роли наследовать права от других ролей (по умолчанию TRUE)
- `REPLICATION`- Позволяет роли использоваться для репликации
- `PASSWORD` - Устанавливает пароль для роли
```sql
CREATE ROLE admin WITH LOGIN PASSWORD 'password' CREATEDB CREATEROLE
```
Пользователя (USER) можно добавить в роль (ROLE). Когда пользователь добавляется в роль, он автоматически наследует все права, связанные с этой ролью.
```sql
-- Создаем роль
CREATE ROLE read_only;
-- Создаем пользователя
CREATE USER myuser WITH PASSWORD 'password';
-- Добавляем пользователя в роль
GRANT read_only TO myuser;
```
```sql
-- удалить пользователя из роли
REVOKE имя_роли FROM имя_пользователя;
```
- `GRANT ALL PRIVILEGES ON DATABASE имя_базы TO имя_пользователя;`
- `DROP USER имя_пользователя;`
- `DROP ROLE имя_роли;`
- `ALTER TABLE` — это команда в SQL, которая используется для изменения структуры уже существующей таблицы в базе данных.
```sql
ALTER TABLE имя_таблицы ADD имя_столбца тип_данных;
```
```sql
ALTER TABLE имя_таблицы DROP COLUMN имя_столбца;
```
```sql
ALTER TABLE имя_таблицы ALTER COLUMN имя_столбца SET DATA TYPE новый_тип;
```
```sql { .code-wrap }
ALTER TABLE имя_таблицы ADD CONSTRAINT имя_ограничения тип_ограничения (столбец);
```
```sql
ALTER TABLE employees ADD CONSTRAINT age_check CHECK (age >= 18);
```
```sql
ALTER DATABASE "<old_name>" RENAME TO "<new_name>";
```
```sql
-- какие роли назначены пользователю
SELECT rolname, memberof
FROM pg_roles
WHERE rolname = 'myuser';
```
---
```sql
-- отключить все подключения к бд
SELECT pg_terminate_backend( pid )
FROM pg_stat_activity
WHERE pid <> pg_backend_pid( ) AND datname = '<database_name>';
```
```sql
-- убить подключение по pid
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE pid = <process_id>;
```
#### Статистика
- `SELECT * FROM pg_stat_activity;` - просмотр текущий подключений
- `SELECT * FROM pg_locks;` - просмотр блокировок
```sql
-- просмотр текущих подключений подробно
SELECT
pid, -- Идентификатор процесса
state, -- Состояние процесса
now() - query_start AS query_runtime, -- Время выполнения текущего запроса
now() - xact_start AS transaction_runtime, -- Время выполнения транзакции
application_name,
query, -- Текущий запрос
usename, -- Пользователь
datname, -- База данных
xact_start -- Время начала транзакции
FROM pg_stat_activity
WHERE state IN ('active', 'idle in transaction') and datname = current_database()
ORDER BY transaction_runtime DESC;
```
```sql
-- смотрим базы и их размер
SELECT pg_database.datname,
pg_size_pretty(pg_database_size(pg_database.datname)) AS size
FROM pg_database
ORDER BY pg_database_size(pg_database.datname) DESC;
```
```sql
-- общий размер конкретной БД
select pg_size_pretty(pg_database_size('название базы'));
```
```sql
-- общий размер индекса в БД
SELECT
pg_size_pretty(SUM(pg_relation_size(indexrelid))) AS total_index_size
FROM
pg_stat_all_indexes;
```
```sql
-- размер таблиц в БД
SELECT
schemaname AS table_schema,
relname AS table_name,
pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
pg_size_pretty(pg_table_size(relid)) AS data_size,
pg_size_pretty(pg_indexes_size(relid)) AS index_size
FROM
pg_catalog.pg_statio_user_tables
ORDER BY
pg_total_relation_size(relid) DESC,
pg_table_size(relid) DESC;
```
```sql
-- размер индексов в БД
SELECT
pg_size_pretty(SUM(pg_relation_size(indexrelid))) AS total_index_size
FROM
pg_index
JOIN
pg_class ON pg_index.indexrelid = pg_class.oid
WHERE
pg_class.relkind = 'i';
```
```sql
-- общий размер индексов в таблице
SELECT
pg_size_pretty(SUM(pg_relation_size(indexrelid))) AS total_index_size
FROM
pg_stat_all_indexes
WHERE
relname = 'название таблицы';
```
```sql
-- имя индексов в таблице и скрипт которым создан индекс
SELECT
indexname,
indexdef
FROM
pg_indexes
WHERE
tablename = 'table_name';
```
```sql
-- блокировки в БД
SELECT
blocked_locks.pid AS blocked_pid,
blocked_activity.usename AS blocked_user,
blocking_locks.pid AS blocking_pid,
blocking_activity.usename AS blocking_user,
blocking_activity.state AS blocking_state,
blocked_activity.query AS blocked_statement,
blocking_activity.query AS current_statement_in_blocking_process,
blocked_locks.locktype AS blocked_locktype,
blocking_locks.locktype AS blocking_locktype
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity
ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks
ON blocking_locks.locktype = blocked_locks.locktype
AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity
ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.GRANTED;
```
```sql
select * from pgstats where tablename = '<table_name>' and attname = '<att_name>'
```
```sql
-- использование памяти и ресурсов в БД
SELECT *
FROM pg_stat_database;
```
??? info "Расшифровка атрибутов `pg_stat_database`"
- `datid` — Идентификатор базы данных (OID).
- `datname` — Имя базы данных.
- `numbackends` — Количество активных соединений (клиентов) с этой базой.
- `xact_commit` — Общее количество успешно завершённых транзакций.
- `xact_rollback` — Общее количество откатов транзакций.
- `blks_read` — Количество блоков, считанных с диска.
- `blks_hit` — Количество блоков, найденных в кеше (попадания в shared_buffers).
- `tup_returned` — Количество строк, возвращённых клиенту.
- `tup_fetched` — Количество строк, извлечённых (например, SELECT).
- `tup_inserted` — Количество вставленных строк (INSERT).
- `tup_updated` — Количество обновлённых строк (UPDATE).
- `tup_deleted` — Количество удалённых строк (DELETE).
- `conflicts` — Количество конфликтов (например, из-за репликации).
- `temp_files` — Количество временных файлов, созданных сервером.
- `temp_bytes` — Количество данных, записанных во временные файлы (в байтах).
- `deadlocks` — Количество взаимоблокировок.
- `blk_read_time` — Общее время чтения блоков с диска (в миллисекундах).
- `blk_write_time` — Общее время записи блоков на диск (в миллисекундах).
### Бэкапирование
По умолчанию pg_dump создает логический бэкап в формате plain (обычный SQL-скрипт)
В PostgreSQL есть два типа дампов:
- `Физические (pg_basebackup)` — побайтовая копия файлов БД.
- `Логические (pg_dump, pg_dumpall)` — SQL-скрипты или архивные файлы.
!!! info ""
`pg_dumpall` создает резервную копию всех баз данных, роли (пользователи и группы), права доступа (GRANT/REVOKE), настройки tablespace, глобальные параметры (например, настройки аутентификации). Умеет отдавать только дамп в формате .sql
`pg_dump` не экспортирует роли, права доступа, tablespaces, параметры кластера (например, `pg_hba.conf`)
1. plain (Текстовый SQL-скрипт)
Описание:
В этом формате по дефолту снимает `pg_dump`. Формат plain представляет собой обычный SQL-скрипт, содержащий скрипты `CREATE TABLE`, `INSERT INTO`, `ALTER TABLE` и другие скрипты для создания и наполнения бд .
Дамп в формате `plain`:
```bash
pg_dump -U postgres -d mydatabase -Fp -f backup.sql
```
Пример содержимого файла дампа:
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT
);
INSERT INTO users (id, name) VALUES (1, 'Alice');
```
- Можно редактировать в текстовом редакторе.
- Можно восстановить частично, скопировав нужные команды.
- Относительно долгое восстановление, так как все данные вставляются скриптами.
Как восстановить:
```bash
psql -U postgres -d mydatabase -f backup.sql
```
2. custom (Сжатый бинарный формат)
Описание:
Формат custom является бинарным, поддерживает сжатие и позволяет восстанавливать отдельные объекты базы данных, такие как таблицы и схемы.
Как создать дамп в формате `custom`:
```bash
pg_dump -U postgres -d mydatabase -Fc -Z 9 -f backup.dump
```
Параметры:
- `Fc` - указывает на использование формата custom.
- `Z 9` - применяет максимальное сжатие дампа.
- `-a` или `--data-only`: Дамп только данных, без схемы
- `-s` или `--schema-only`: Дамп только схемы, без данных
- `-O` или `--no-owner`: Исключает команды SET OWNER из дампа
- `-x` или `--no-privileges`: Исключает команды GRANT/REVOKE из дампа.
- Поддерживает выборочное снятие отдельных объектов.
- Поддерживает параллельное снятие с `-j`.
Посмотреть содержимое дампа без восстановления:
```bash
pg_restore -l backup.dump
```
Как восстановить базу данных:
```bash
pg_restore -U postgres -d mydatabase -f backup.dump
```
3. directory (Каталог с дампом)
Описание:
Формат `directory` сохраняет резервную копию в виде каталога, содержащего отдельные файлы для каждой таблицы и других объектов базы данных. Этот формат позволяет параллельно снимать бэкап.
Дамп в формате `directory`:
```bash
pg_dump -U postgres -d mydatabase -Fd -j4 -f backup_dir/
```
Параметры:
- `Fd` — указывает на формат directory.
- `j4` — использует 4 параллельных потока для ускорения процесса.
- Можно восстанавливать отдельные таблицы и объекты.
Восстановление
```bash
pg_restore -U postgres -d mydatabase -j 4 backup_dir/
```
4. tar (Архив tar)
Описание:
Формат tar создает архив tar, содержащий все необходимые файлы для восстановления базы данных. Он удобен для хранения и передачи, но восстановление в данном формате выполняется медленнее по сравнению с `directory` или `custom`.
Дамп в формате `tar`:
```bash
pg_dump -U postgres -d mydatabase -F t -f backup.tar
```
Параметры:
- Ft — указывает на формат tar.
- Медленное восстановление, так как данные сначала извлекаются из архива.
Восстановление бд:
```bash
pg_restore -U postgres -d mydatabase -Ft backup.tar
```
!!! info ""
Все форматы дампов кроме `.sql` восстанавливаются через `pg_restore`
#### Пример организации бэкапирования
Скрипт `backup.sh` для снятия бэкапа, удаления бэкапов
```bash
#!/bin/bash
if [ "$#" -ne 3 ]; then
echo "Необходимо передать три аргумента."
echo "Пример: $0 <имя_стенда> <имя_базы_данных> <время_жизни_бэкапа_в_днях>"
exit 1
fi
PG_PASSWORD="postgres"
PG_PORT="5432"
STAND_NAME="$1"
DB_NAME="$2"
BACKUP_TTL="$3"
BACKUP_DIR="/opt/backups/${STAND_NAME}"
BACKUP_FILE="${STAND_NAME}_$(date +%Y%m%d).dump"
LOG_DIR="${BACKUP_DIR}/logs"
LOG_FILE="${LOG_DIR}/backup_${STAND_NAME}.log"
mkdir -p "${BACKUP_DIR}"
mkdir -p "${LOG_DIR}"
echo "$(date +%Y%m%d_%H%M%S) Начало резервного копирования базы данных ${DB_NAME}" >> ${LOG_FILE}
PGPASSWORD=${PG_PASSWORD} pg_dump -p ${PG_PORT} -h localhost -U postgres -d ${DB_NAME} -Fc -Z 9 -f "${BACKUP_DIR}/${BACKUP_FILE}" 2>> ${LOG_FILE}
if [ $? -eq 0 ]; then
echo "$(date +%Y%m%d_%H%M%S) Резервное копирование успешно завершено: ${BACKUP_DIR}/${BACKUP_FILE}" >> ${LOG_FILE}
find ${BACKUP_DIR} -type f -name "*.dump" -mtime +${BACKUP_TTL} -exec rm {} \;
if [ $? -eq 0 ]; then
echo "$(date +%Y%m%d_%H%M%S) Бэкапы старше ${BACKUP_TTL} дней удалены." >> ${LOG_FILE}
else
echo "$(date +%Y%m%d_%H%M%S) Ошибка при удалении бэкапов." >> ${LOG_FILE}
fi
else
echo "$(date +%Y%m%d_%H%M%S) Ошибка при резервном копировании базы данных ${DB_NAME}" >> ${LOG_FILE}
fi
```
Добавить в `cron`
```bash
# Для снятия бэкапа: <путь к скрипту> <имя каталога для бэкапа> <имя базы данных стенда> <кол-во хранимых бэкапов>
00 23 * * * /opt/backups/backup.sh stand1 database1 3
59 23 * * * /opt/backups/backup.sh stand2 database2 3
```
### Разное
- `ps -ef | grep -v grep | grep postgres` - определяет есть ли процесс постгрес на машине
- `which psql` - есть ли в локальном окружении psql
- `sudo docker inspect <имя_контейнера> | grep postgres` - есть ли постгрес в контейнере
---
- `psql -U postgres -c "SHOW server_version;"` - версия пг или `psql -V` или `/usr/bin/psql -V`
- `psql -U postgres -c "SHOW port;"` - порт на котором работает пг
- `psql -U postgres -c "SHOW wal_directory;"` - каталог WAL
#### Где что лежит??
1. Каталог данных
- `/var/lib/postgresql/<версия>/main/` - Debian/Ubuntu
- `/var/lib/pgsql/<версия>/data/` - CentOS/Fedora
- `psql -U postgres -c "SHOW data_directory;"`
2. Конфигурационные файлы (могут находится в каталоге данных)
- `/etc/postgresql/<версия>/main/`
- `psql -U postgres -c "SHOW config_file;"` - путь к конфигу
- `psql -U postgres -c "SHOW hba_file;"` - путь к настройкам аутентификации
3. Каталог логов
- `/var/log/postgresql/`
- `psql -U postgres -c "SHOW log_directory;"`
---
- `SHOW shared_preload_libraries;` - список библиотек, которые были загружены при старте PostgreSQL с помощью параметра `shared_preload_libraries` в `postgresql.conf`
- `pg_config --pkglibdir` - показывает путь к каталогу, где находятся библиотеки пг (shared libraries).