Оглавление

Архитектура

Архитектура ANSI_SPARC

Включает в себя три уровня.
1. Внешний (пользовательскй) уровень - представляет их данные так, как их видят конечные пользователи. У разных пользователей могут быть разные представления одной и той же базы - например, один видит только часть таблиц или полей.
- Реализуется через представления
- На этом уровне пользовательские запросы и интерфейсы
2. Промежуточный (концептуальный) уровень - описывает структуру базы данных. Здесь задаются таблицы, структура таблиц, связи между ими, схемы. Определяет логическую структуру данных (столбцы, типы данных, связи). Это описание бд в целом без привязки к тому, как она хранится.
3. Внутренний (физический) уровень - описывает, как физически хранятся данные. С этим уровнем пользователи напрямую не работают.
- Реализуется через файлы данных, индексы, WAL
- Тут происходит управление страницами и блоками
- Стратегии хранения и доступа к данным.
PostgreSQL следует этой модели

  1. Пользователь видит таблицы и представления (внешний уровень)
  2. Админ определяет схемы и отношения (концептуальный)
  3. Система управляет табличными пространствами, файлами, индексами (физический)

Структура СУБД

Архитектура PostgreSQL

Постргрес - объектно-реляционная клиент-серверная СУБД.
Общая идея: клиенты -> Серверные процессы -> Память -> Диск
postgres_arch

Разделяемое буферное пространство (Shared Buffers)
WAL buffers
CLOG buffers
Lock space
Буферное пространство процессов (неразделяемая область памяти процессов)

В режиме выделенного сервера каждому пользовательскому процессу создается свой "персональный" серверный
В режиме разделяемого сервера для каждого пользвательского процесса серверный процесс выделяется диспетчером из специального пула. Пул управляется с помощью pgBouncer. Он держит пул соединений, переиспользует их и ускоряет подключение.

Системный каталог

В постгре есть возможность получать данные о метаданных: когда была создана таблица, сколько и какие в ней атрибуты, какие индексы связаны с таблицей. Для доступа к метаданным используются таблицы и представления - системные каталоги.
У каждой БД есть схема pg_catalog, в ней каталоги. относящиеся к этой БД

Работа с системным каталогом
Схема

Управление доступом к БД

Пользовательские права

Разным категориям юзеров должны предоставляться разные возможности для управления различными объектами БД
Возможности - обеспечение доступа (или выполнения другой операции) с таблицами, представлениями, создание пользователей.
Представляемые возможности определяются привилегиями:

Роли

Привилегии отражают конкретную возможность.
Роли - именованные наборы привилегий, позволяющие управлять объектами и бд на более высоком уровне. Могут выступать в качестве пользователей.
Роль конфигурируется на уровне кластера. Назначение и привилегии могут отличаться в разных БД. Имя роли уникально для кластера.
CREATE ROLE ... WITH LOGIN PASSWORD 'PSWD'
CREATE ROLE ... CREATEROLE
ALTER ROLE, DROP ROLE
Эти команды могут использовать суперпользователи и роли с CREATEROLE (не на суперпользователях)

Пользователи

При установке кластера создается админ postgres
Пользователи созданы для отображения именованных пользователей системы. Они могут быть созданы суперпользователем и пользователем с ролью CREATEROLE.
CREATE USER... == CREATE ROLE ... WITH LOGIN
При создании БД создается роль public. Он назначается всем пользователям и ролям - определяет права пользователей и ролей по умолчанию к разным объектам.
Настройка через pg_roles
В постгре нет отдельных пользователей. Пользователь - это просто роль с правами входа (LOGIN). Ну и пользователи обычно не используются как группы.

Настройка ролей:

Группы ролей

Роли можно объединять в группы для более гибкого управления ими. При добавлении пользователя в группу пользователь наследует ее привилегии.

CREATE ROLE students;
GRANT INSERT ON table_name TO students;
GRANT students TO user1;

Таким образом первый юзер получает все права роли студенты. Это используется для того, чтобы не выдавать права каждому пользователю отдельно, а управлять ими централизованно.

Админ группы ролей - человек, который может управлять группой (добавлять, удалять участников). Эта роль не дает ему всех привилегий, но позволяет управлять своей группой.
GRANT students TO user1 WITH ADMIN OPTION

INHERIT - поведение по умолчанию. В этом случае пользователь автоматически получает права всех ролей, в которые входит
NOINHERIT - пользователь не получает права автоматически. Ему нужно явно переключиться на нужную роль SET ROLE sudents. Это используется для разделения обычных и привилегированных действий. (можно сидеть как обычный юзер, а потом переключиться на админа и тыкаться как админ). Указывается при создании роли (не группы)

Поиск привилегий идет так:

  1. Поиск среди привилегий роли
  2. Поиск среди родителей (если inherit), поиск среди прародителей (если у родителей inherit)
  3. Есть ли привилегия для public

Для отмены привилегий: REVOKE priv1 ON table1 To user1

Работа с PostgreSQL

Установка и запуск PostgreSQL

Есть два варианта:

Устанавливаются базовые компоненты PSQL

Процесс установки
  1. Установка (сборка) базовых компонентов (пакетов): sudo apt install postgresql-xx postgresql-client-xx ..
  2. Создание системного пользователя postgres: adduser postgres, mkdir [PGDATA], chown postgres [PGDATA]
  3. Задание переменных окружений: PGDATA, ...
  4. Инициализция кластера [/pg_path]/bin/initdb [-D PGDATA_path]
  5. Запуск экземпляра кластера БД
    1. postgres [-D PGDATA_path]
    2. pg_ctl [-D PGDATA_path] -l logfile start
    3. Сервис: sudo service postgresql start
Инициализация кластера initdb
Инициализация

Базы данных доступные после установки:

templte0, template1
Запуск сервера базы данных

[/pg_path]/bin/postgres [-D pgdata_path]
Можно заранее установить переменную PGDATA:
PGDATA = ...
esport PGDATA
postgres
! PGDATA должна быть проинициализирована перед запуском постгри

Утилита pg_ctl

Нужна для упрощения взаимодействия с постгрей. Можно запускать (по умолчанию в фоне), останавливать, перезапускать кластер

Подключение к БД PostgreSQL

Варианты клиентов:

Для подключения к БД роль должна быть:

Подключение к серверу БД
  1. Запуск сервера postgres -p 2222 -D /home/myuser/pgd/data
  2. Подключаем клиент psql -p 1234
  3. Экземпляр проверяет, может ли клиент получить доступ
  4. Если проверка прошла успешно, создается серверный процесс для обработки соединения данного клиента
pg_hba.conf
pg_hba

Создание БД в PSQL

Создание из шаблона

По умолчанию клонится template1
Но можно и другую бд использовать: CREATE DATABASE newDb TEMPLATE oldDb или проще createdb -T oldDb newDb
Чтобы база могла быть шаблоном нужно, чтобы к ней не было подключений других пользователей.

В системном каталоге pg_database есть поля

Файловая структура и конфигурация PSQL

PGDATA - путь к директории данных кластера, установлена заранее

Файлы данных

Базовые конфиг файлы:

Изменение конфигурационных параметров:

  1. postgresql.conf / ALTER SYSTEM - на уровне кластера
  2. ALTER DATABASE - изменить параметр на уровне бд (применяется при запуске новой сессии)
  3. ALTER ROLE - переписать 1. и 2. на уровне пользователя (тоже при запуске новой сессии)
  4. SET - изменить для сессии (`SET param TO value /DEFAULT)
  5. Параметры можно задать в команде запуска сервера БД (postgres) - для переписи парметров postgresql.conf

Табличные пространства

Табличные пространства позволяют задать пути (директорию в фс), где будут храниться объекты БД (вне PGDATA)
Это позволяет управлять физическим расположением объектов БД

Стандартные тс:

Так накой же они нам вообще нужны?

Транзакции

Минутка так называемой базы для тех, кто еще хоть чуть чуть помнит ИС

ACID
Atomacity (атомарность)

Гарантирует, что результаты работы транзакции не будут зафиксирован в системе частично
Будут выполнены либо все операции, либо ни одной

Consistency (согласованность)

После выполнения транзакции бд должна быть в целостном состоянии
Во время выполнения транзакции согласованность не требуется

Isolation (изолированность)

Во время выполнения транзакции другие транзакции (выполняющиеся параллельно) не должны оказывать влияние на результат транзакции

Durability (долговечность)

При успешном завершении транзакции результаты ее работы должны остаться в системе независимо от возможных сбоев оборудования, системы и тд

Какими бывают транзакции:

BASE

Альтернативой ACID для распределенных баз данных является концепция BASE (опирающаяся на CAP-теорему):

Время и транзакции

Идентификация транзакций

Скрытые поля или где же искать этот ваш xid

Возможные значения:

Могут ли закончиться? Ну тогда у нас просто заново с 3 начнется выдача. Но вообще есть такая шняга, как статус FROZEN для неактуальных записей, но про это в разделе VACUUM
Ну и быстро вспомним что у нас был такой CLOG-буфер, который хранит статус транзакций:

Реализация транзакций в PSQL

Как это сделано в постгре?
Реализация транзакций в постгре - MVCC
Multi-Version Concurrency Control
В постгре - Serializable Snapshot Isolation (SSI)
Особенность в том, что при изменении данных в транзакции создается новая копия данных. А существующие копии не изменяются. При выборки данных берется подходящая для данной транзакции версия данных. Но даже не смотря на это у нас все же иногда случается блокировка исполнения транзакции.

Изоляция транзакций

При параллельном доступе к данным у нас может возникнуть три вида проблем:

И есть у нас 4 уровня изоляции

  1. Read Uncommitted (в постгре его нет) - возможно возникновение всего на свете
  2. Read Committed - по умолчанию - исключает возможность грязного чтения
  3. Repeatable Read - исключает еще и неповторяющееся чтение (в постгре на самом деле и фантомку тоже из-за MVCC, но по стандарту нет. А вот аномалии сериализации никуда не делись)
    Аномалии сериализации - параллельные транзакции дают результат, которых невозможен, если бы они выполнялись по очереди. В постгре для Serializable используется SSI, помогающий этого избежать
  4. Serializable - максимальная изоляция и симуляция поведения как при последовательном выполнениии, так что исключает все проблемы
Snapshot Isolation (SI)

VACUUM

Реализация транзакций в постгре - MVCC
Multi-Version Concurrency Control
В постгре - Serializable Snapshot Isolation (SSI)
Особенность в том, что при изменении данных в транзакции создается новая копия данных. А существующие копии не изменяются. Надо что-то делать!
А что делать? А удалять) И для удаления таких записей и используется VACUUM
VACUUM table [table 2]

VACUUM

Выполнение операций и восстановление данных

M - memory, D - disk, T - transaction
Операции для синхронизации различных пространств памяти:

Для предотвращения ситуаций, связанных с появлением несогласованных данных можно использовать журнал (лог)
СУБД сохраняет информацию об изменениях и фиксациях данных в журнале:

UNDO-журнал

Возможные записи в журнале отмены:

Правила записи в UNDO LOG
Использование журнала отмены для восстановления данных
Контрольные точки

Для восстановления данных нужна какая-то стартовая точка, чтобы не анализировать транзакции с самого начала работы с БД.
Контрольная точка (checkpoint) - точка синхронизации, во время которой происходит синхронизация данных из буферов с соответствующими файлами на диске
Создаются они так:

  1. В журнал добавляется START CHKn: Tn...TmT_n...T_m, фиксируется на диске через WriteLog
  2. Ожидание завершения транзакций, которые работали в момент создания КТ. В это время могут начинаться другие транзакции
  3. В журнал добавляется END CHKn, фиксируется на диске
  4. Записи перед START CHKn, у которой есть END CHKn могут быть удалены

Действия при восстановлении данных:

Для тех, кто ничего не понял:
Контрольная точка используется для сокращения объёма журнала, необходимого для восстановления, чтобы не читать лог с самого начала. Она создаётся по времени, по объёму WAL или вручную.
При записи START CHK фиксируется список активных транзакций. Затем система ожидает их завершения (COMMIT или ABORT), после чего записывается END CHK, означающий успешное завершение контрольной точки.
После завершения checkpoint можно удалять устаревшие записи журнала, относящиеся к более ранним контрольным точкам.
При восстановлении возможны два сценария:

Недостатки UNDO LOG

REDO-журнал

Возможные записи в журнале повторений:

Правила записи в REDO LOG
Использование журнала повторений для восстановления данных
Контрольные точки

Контрольная точка в REDO используется для сокращения объёма журнала при восстановлении.
При её создании сначала записывается START CHK со списком активных транзакций, затем происходит запись на диск всех “грязных” страниц, относящихся к завершённым транзакциям, и после этого фиксируется END CHK.
Checkpoint не ожидает завершения активных транзакций.
При восстановлении:

Недостатки REDO LOG

UNDO/REDO-журнал

Возможные записи:
Возможные записи в журнале повторений:

Правила записи в REDO LOG
Использование для восстановления данных
Контрольные точки

При создании записывается START CHK со списком активных транзакций, затем на диск сбрасываются все “грязные” страницы, включая данные незавершённых транзакций, после чего записывается END CHK.
Checkpoint не ожидает завершения транзакций.
При восстановлении:

steal/no-steal, force/no-force

ARIES - алгоритм для восстановления данных, который базируется на
wal + steal + no-force
Происходит в три этапа:

Резервное копирование

Стратегия РК:

Логическое РК

pg_dump mydb > dump.sql
pg_dump -Fc -f dump mydb
pg_restore -d mydb dump
pg_dump

Форматы pg_dump:

pg_dumpall
Плюсы РК
Минусы

Физическое РК

Подходы:

Копирование фс

Полное копирование PGDATA. Обычно на холодную или через снапшот данных. Копируется ток вся бд целиком, выбрать отдельные таблицы нельзя

Непрерывное архивирование
Физическое РК + WAL
Этапы для реализации непрерывного архивирования
  1. Организация архивирования WAL
  2. Создание базовой резервной копии

Этап 1:

pg_basebackup

pg_basebackup -D /backup
Делает физическую копию кластера, может работать из запущенной бд, используется для репликации.

pg_start_backup / pg_stop_backup
SELECT pg_start_backup('label');  
-- создается backup_my_label файл, который содержит инфу о рк
-- создается КТ и tablespace_map
-- пользователем производится копирование файлов кластера БД
SELECT pg_stop_backup();

инициализирует бэкап режим, создает чекпоинт и фиксирует консистентное состояние

Восстановление
  1. Остановить сервер
  2. Если возможно - сделать копию хотя бы pg_wal
  3. Проверить наличие бэкапа. Если есть - удалить PGDATA и внешние директории (если есть)
  4. Скопировать в PGDATA и внешние директории данные ранее полученного бэкапа
  5. Очистить PGDATA/pg_wal
  6. Если есть незаархивированные WAL c шага 2 - поместить их в pg_wal
  7. Установить настройки для восстановления в postgresql.conf (restore_command возвращает не 0 при неудаче) + запретить внешние подключения для юзеров в pg_hba.conf
  8. Создать файл recovery.signal - говорит серверу, что надо стартовать в режиме восстановления
  9. Запустить сервер
  10. Разрешить подключение пользователей
restore_command

Репликация

Репликация — процесс дублирования данных с одного сервера базы данных на другие для повышения надежности, обеспечения отказоустойчивости и балансировки нагрузки.

Виды репликации

По способу синхронизации (отправки подтверждения):

По передаваемым данным:

Физическая репликация в PostgreSQL

Основана на передаче файлов WAL (Write-Ahead Log) от ведущего сервера к потоковой реплике (Standby).
Реплика находится в режиме постоянного восстановления (Continuous Recovery) и непрерывно применяет приходящие WAL.
Ключевые настройки:

Логическая репликация в PostgreSQL

Основывается на логическом декодировании (Logical Decoding) — разборе потока WAL в понятные логические операции.

Различные топологии и подходы

CAP теорема

В распредёленной системе невозможно одновременно обеспечить все три свойства, нужно выбрать два:

Масштабирование и шардирование

Масштабирование — процесс расширения адаптационных возможностей БД при росте нагрузки (увеличении объема данных и количества запросов).

Шардирование

Шардирование (Sharding) — метод горизонтального масштабирования, при котором данные логически одной базы (например, гигантская таблица) разделяются по кускам (шардам) и хранятся на различных независимых узлах.

Перебалансировка (Rebalancing) при шардировании
Процесс миграции данных между шардами, например, при добавлении в кластер новых серверов для поддержания баланса.
Методы балансировки зависят от способа логического деления ключа (Hash, Range, List), но зачастую перенос больших кусков данных (при изменении числа серверов) является сложной алгоритмической и эксплуатационной задачей.

Ассиметричное шардирование
Возникает из-за дисбаланса, когда некоторые шарды перегружаются запросами по сравнению с остальными.
Чаще всего вызвано наличием горячих диапазонов ("hot spots") или неравномерным хэшированием ключа.
Способы решения данной проблемы: