diff --git a/backups/wal_e.tex b/backups/wal_e.tex index f18f5192..23d85558 100644 --- a/backups/wal_e.tex +++ b/backups/wal_e.tex @@ -21,7 +21,7 @@ \subsubsection{Установка} \subsubsection{Настройка и работа} -Как уже писалось, WAL-E сливает все данные в AWS S3, поэтому нам потребуются <>, <> и <> (эти данные можно найти в акаунте Amazon AWS). Команда для загрузки бэкапа всей базы данных в S3: +Как уже писалось, WAL-E сливает все данные в AWS S3, поэтому нам потребуются <>, <> и <> (эти данные можно найти в аккаунте Amazon AWS). Команда для загрузки бэкапа всей базы данных в S3: \begin{lstlisting}[language=Bash,label=lst:wal-e3,caption=Загрузка бэкапа всей базы данных в S3] AWS_REGION=... AWS_SECRET_ACCESS_KEY=... wal-e \ diff --git a/clustering/citus.tex b/clustering/citus.tex index 3ae2532d..3e8b5da4 100644 --- a/clustering/citus.tex +++ b/clustering/citus.tex @@ -1,12 +1,12 @@ \section{Citus} \label{sec:citus} -\href{https://www.citusdata.com/}{Citus}~--- горизонтально масштабируемый PostgreSQL кластер. Citus использует механизм расширений PostgreSQL вместо того, что бы использовать модифицированную версию базы (как это делает <<\ref{sec:postgres-x2}~\nameref{sec:postgres-x2}>> или <<\ref{sec:postgres-xl}~\nameref{sec:postgres-xl}>>), что позволяет использовать новые версии PostgreSQL с новыми возможностями, сохраняя при этом совместимость с существующими PostgreSQL инструментами. Кластер предоставляет пользователям результаты запросов в режиме <<реального времени>> для большого и растущего обьема данных (благодаря параллелизации запросов между нодами). Примеры использования: +\href{https://www.citusdata.com/}{Citus}~--- горизонтально масштабируемый PostgreSQL кластер. Citus использует механизм расширений PostgreSQL вместо того, что бы использовать модифицированную версию базы (как это делает <<\ref{sec:postgres-x2}~\nameref{sec:postgres-x2}>> или <<\ref{sec:postgres-xl}~\nameref{sec:postgres-xl}>>), что позволяет использовать новые версии PostgreSQL с новыми возможностями, сохраняя при этом совместимость с существующими PostgreSQL инструментами. Кластер предоставляет пользователям результаты запросов в режиме <<реального времени>> для большого и растущего объема данных (благодаря параллелизации запросов между нодами). Примеры использования: \begin{itemize} \item аналитика и вывод данных в реальном времени на графики; \item хранение большого набора данных для архива и создание отчетов по ним; - \item анализ и сегментация большого обьема данных; + \item анализ и сегментация большого объема данных; \end{itemize} Нагрузки, которые требуют большой поток данных между узлами кластера, как правило, не будет хорошо работать с Citus кластером. Например: @@ -60,7 +60,7 @@ \subsection{Распределенные таблицы} Следующим шагом после выбора столбца на распределения будет определение правильного метода распределения данных в таблицу. В целом, существует два шаблона таблиц: распределенные по времени (время создания заказа, запись логов, прочее) и распределение по идентификатору (ID пользователя, ID приложения, прочее). Citus поддерживает оба метода распределения: append и hash соответственно. -Append метод подходит для таблиц, в которые записываются данные по времени (упорядочены по времени). Такой тип таблиц отлично справляется с запросами, которые использут фильтры с диапазонами значений по распределенному столбцу (\lstinline!BETWEEN x AND y!). Это обьясняется тем, что мастер хранит диапазоны значений, которые хранятся на шардах, и планировщик может эффективно выбирать шарды, которые содержат данные для SQL запроса. +Append метод подходит для таблиц, в которые записываются данные по времени (упорядочены по времени). Такой тип таблиц отлично справляется с запросами, которые используют фильтры с диапазонами значений по распределенному столбцу (\lstinline!BETWEEN x AND y!). Это объясняется тем, что мастер хранит диапазоны значений, которые хранятся на шардах, и планировщик может эффективно выбирать шарды, которые содержат данные для SQL запроса. Hash метод распределения подходит для неупорядоченного столбца (user UUID) или по данным, которые могут записываться в любом порядке. В таком случае Citus кластер будет хранить минимальные и максимальные значения для хеш функций на всех шардах. Эта модель лучше подходит для SQL запросов, включающих фильтры на основе равенства по колонке распределения (\lstinline!user_uuid='a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'!). diff --git a/clustering/greenplum.tex b/clustering/greenplum.tex index 18e5deae..79cab923 100644 --- a/clustering/greenplum.tex +++ b/clustering/greenplum.tex @@ -137,7 +137,7 @@ \subsection{Взаимодействие с клиентами} # На ETL-сервере: bash# for i in {1..1000}; do echo "$i,$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)"; done > /tmp/work/gpfdist_home/test_table.csv -# Теперь создаим внешнюю таблицу и прочитаем данные из файла +# Теперь создадим внешнюю таблицу и прочитаем данные из файла # В Greenplum DB: db=# create external table ext_test_table db-# (id integer, rand varchar(8)) diff --git a/clustering/postgres_xl.tex b/clustering/postgres_xl.tex index af236e02..e612252b 100644 --- a/clustering/postgres_xl.tex +++ b/clustering/postgres_xl.tex @@ -1,14 +1,14 @@ \section{Postgres-XL} \label{sec:postgres-xl} -Postgres-XL~-- система для создания мульти-мастер кластеров, работающих в синхронном режиме~-- все узлы всегда содержат актуальные данные. Проект построен на основе кодовой базы Postgres-X2, поэтому артитектурный подход полностью идентичен (глобальный менеджер транзакций (GTM), координаторы (coordinators) и обработчики данных (datanodes)). Более подробно про архитектуру можно почитать в <<\ref{sec:postgres-x2-architecture}~\nameref{sec:postgres-x2-architecture}>> разделе. Поэтому рассмотрим только отличие Postgres-X2 и Postgres-XL. +Postgres-XL~-- система для создания мульти-мастер кластеров, работающих в синхронном режиме~-- все узлы всегда содержат актуальные данные. Проект построен на основе кодовой базы Postgres-X2, поэтому архитектурный подход полностью идентичен (глобальный менеджер транзакций (GTM), координаторы (coordinators) и обработчики данных (datanodes)). Более подробно про архитектуру можно почитать в <<\ref{sec:postgres-x2-architecture}~\nameref{sec:postgres-x2-architecture}>> разделе. Поэтому рассмотрим только отличие Postgres-X2 и Postgres-XL. \subsection{Postgres-X2 и Postgres-XL} Одно из главных отличий Postgres-XL от Postgres-X2 является улучшенный механизм массово-параллельной архитектуры (massive parallel processing, MPP). Чтобы понять разницу, давайте рассмотрим как Postgres-X2 и Postgres-XL будет обрабатывать разные SQL запросы. Оба этих кластера будут содержать три таблицы \lstinline!T1!, \lstinline!T2! и \lstinline!R1!. \lstinline!T1! имеет колонки \lstinline!a1! и \lstinline!a2!, \lstinline!T2!~--- \lstinline!b1! и \lstinline!b2!. \lstinline!T1! распределена в кластере по \lstinline!a1! полю и \lstinline!T2! распределена по \lstinline!b1! полю. \lstinline!R1! таблица имеет колонки \lstinline!c1! и \lstinline!c2! и реплицируется в кластере (\lstinline!DISTRIBUTE by REPLICATION!). -Для начала, простой запрос вида \lstinline!SELECT * FROM T1! будет паралельно выполняться на нодах как у Postgres-X2, так и у Postgres-XL. Другой пример запроса \lstinline!SELECT * FROM T1 INNER JOIN R1 ON T1.a1 = R1.c1! будет также выполняться паралельно обоими кластерами, потому что будет передан (<>) на обработчики данных (datanodes) для выполнения и координатор (coordinators) будет только агрегировать (собирать) результаты запросов. Это будет работать благодаря тому, что \lstinline!R1! таблица дублицируется на каждом обработчике данных. Этот тип запросов будет работать хорошо, когда \lstinline!T1! является \href{https://en.wikipedia.org/wiki/Fact\_table}{таблицей фактов} (основной таблицей хранилища данных), в то время как \lstinline!R1!~--- \href{https://en.wikipedia.org/wiki/Dimension\_(data\_warehouse)#Dimension\_table}{таблицей измерений} (содержит атрибуты событий, сохраненных в таблице фактов). +Для начала, простой запрос вида \lstinline!SELECT * FROM T1! будет параллельно выполняться на нодах как у Postgres-X2, так и у Postgres-XL. Другой пример запроса \lstinline!SELECT * FROM T1 INNER JOIN R1 ON T1.a1 = R1.c1! будет также выполняться параллельно обоими кластерами, потому что будет передан (<>) на обработчики данных (datanodes) для выполнения и координатор (coordinators) будет только агрегировать (собирать) результаты запросов. Это будет работать благодаря тому, что \lstinline!R1! таблица дублицируется на каждом обработчике данных. Этот тип запросов будет работать хорошо, когда \lstinline!T1! является \href{https://en.wikipedia.org/wiki/Fact\_table}{таблицей фактов} (основной таблицей хранилища данных), в то время как \lstinline!R1!~--- \href{https://en.wikipedia.org/wiki/Dimension\_(data\_warehouse)#Dimension\_table}{таблицей измерений} (содержит атрибуты событий, сохраненных в таблице фактов). Теперь рассмотрим другой вариант SQL запроса: @@ -18,9 +18,9 @@ \subsection{Postgres-X2 и Postgres-XL} Данный запрос делает \lstinline!JOIN! по распределенной колонке \lstinline!a1! в таблице \lstinline!T1! и по НЕ распределенной колонке \lstinline!b2! в таблице \lstinline!T2!. В кластере, который состоит из 4 обработчиков данных, колонка в таблице \lstinline!T1! на первом из них потенциально требуется объединить с колонками таблицы \lstinline!T2! на всех обработчиках данных в кластере. -У Postgres-X2 в данном случае обработчики данных отправляют все данные по заданому условию в запросе к координатору, который и занимается объединением данных с таблиц. В данном примере отсутствует условие \lstinline!WHERE!, что значит, что все обработчики данных отправят все содержимое таблиц \lstinline!T1! и \lstinline!T2! на координатор, который и будет делать \lstinline!JOIN! данных. В данной операции будет отсутствовать паралельное выполнение \lstinline!JOIN! запроса и будут дополнительные накладные расходы на доставку всех данных к координатору. Поэтому в данном случае Postgres-X2 фактически будет медленее, чем выполнение подобного запроса на обычном PostgreSQL сервере (особенно, если таблицы очень большие). +У Postgres-X2 в данном случае обработчики данных отправляют все данные по заданному условию в запросе к координатору, который и занимается объединением данных с таблиц. В данном примере отсутствует условие \lstinline!WHERE!, что значит, что все обработчики данных отправят все содержимое таблиц \lstinline!T1! и \lstinline!T2! на координатор, который и будет делать \lstinline!JOIN! данных. В данной операции будет отсутствовать параллельное выполнение \lstinline!JOIN! запроса и будут дополнительные накладные расходы на доставку всех данных к координатору. Поэтому в данном случае Postgres-X2 фактически будет медленнее, чем выполнение подобного запроса на обычном PostgreSQL сервере (особенно, если таблицы очень большие). -Postgres-XL будет обрабатывать подобный запрос по-другому. Условие \lstinline!T1.a1 = T2.b2! говорит о том, что мы объединяем колонку \lstinline!b2! с колонкой \lstinline!a1!, которая является ключом распределения для таблицы \lstinline!T1!. Поэтому, выбрав значения поля \lstinline!b2!, кластер будет точно знать для каких обработчиков данных требуется полученый результат для объединения с таблицей \lstinline!T1! (поскольку возможно применить хеш функцию распределения на полученые значения). Поэтому каждый обработчик данных считает с другого обработчика данных требуемые данные по таблице \lstinline!T2! для объединения со своей таблицей \lstinline!T1! без участия координатора. Данная возможность прямой коммуникации обработчиков данных с другими обработчиками данных позволяет распараллеливать более сложные запросы в Postgres-XL. +Postgres-XL будет обрабатывать подобный запрос по-другому. Условие \lstinline!T1.a1 = T2.b2! говорит о том, что мы объединяем колонку \lstinline!b2! с колонкой \lstinline!a1!, которая является ключом распределения для таблицы \lstinline!T1!. Поэтому, выбрав значения поля \lstinline!b2!, кластер будет точно знать для каких обработчиков данных требуется полученный результат для объединения с таблицей \lstinline!T1! (поскольку возможно применить хеш функцию распределения на полученные значения). Поэтому каждый обработчик данных считает с другого обработчика данных требуемые данные по таблице \lstinline!T2! для объединения со своей таблицей \lstinline!T1! без участия координатора. Данная возможность прямой коммуникации обработчиков данных с другими обработчиками данных позволяет распараллеливать более сложные запросы в Postgres-XL. Postgres-XL имеет также другие улучшения производительности (более оптимально обрабатываются последовательности, прочее). diff --git a/extensions/cstore_fdw.tex b/extensions/cstore_fdw.tex index 624af323..d199f5ee 100644 --- a/extensions/cstore_fdw.tex +++ b/extensions/cstore_fdw.tex @@ -1,6 +1,6 @@ \section{Cstore\_fdw} -\href{https://citusdata.github.io/cstore\_fdw/}{Cstore\_fdw} расширение реализует модель хранения данных на базе \href{https://en.wikipedia.org/wiki/Column-oriented\_DBMS}{семейства столбцов} (column-oriented systems) для PostgreSQL (колоночное хранение данных). Такое хранение данных обеспечивает заметные преимущества для аналитических задач (\href{https://ru.wikipedia.org/wiki/OLAP}{OLAP}, \href{https://en.wikipedia.org/wiki/Data\_warehouse}{data warehouse}), поскольку требуется считывать меньше данных с диска (благодаря формату хранения и компресии). Расширение использует \href{https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC#LanguageManualORC-ORCFileFormat}{Optimized Row Columnar (ORC)} формат для размещения данных на диске, который имеет следующие преимущества: +\href{https://citusdata.github.io/cstore\_fdw/}{Cstore\_fdw} расширение реализует модель хранения данных на базе \href{https://en.wikipedia.org/wiki/Column-oriented\_DBMS}{семейства столбцов} (column-oriented systems) для PostgreSQL (колоночное хранение данных). Такое хранение данных обеспечивает заметные преимущества для аналитических задач (\href{https://ru.wikipedia.org/wiki/OLAP}{OLAP}, \href{https://en.wikipedia.org/wiki/Data\_warehouse}{data warehouse}), поскольку требуется считывать меньше данных с диска (благодаря формату хранения и компрессии). Расширение использует \href{https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC#LanguageManualORC-ORCFileFormat}{Optimized Row Columnar (ORC)} формат для размещения данных на диске, который имеет следующие преимущества: \begin{itemize} \item Уменьшение (сжатие) размера данных в памяти и на диске в 2-4 раза. Можно добавить в расширение другой кодек для сжатия (алгоритм Лемпеля-Зива, LZ присутствует в расширении); diff --git a/extensions/hstore.tex b/extensions/hstore.tex index 1cb5b414..4096cd7e 100644 --- a/extensions/hstore.tex +++ b/extensions/hstore.tex @@ -3,7 +3,7 @@ \section{HStore} \href{https://www.postgresql.org/docs/current/static/hstore.html}{HStore}~-- расширение, которое реализует тип данных для хранения ключ/значение в пределах одного значения в PostgreSQL (например, в одном текстовом поле). Это может быть полезно в различных ситуациях, таких как строки со многими атрибутами, которые редко выбираются, или полу-структурированные данные. Ключи и значения являются простыми текстовыми строками. -Начиная с версии 9.4 PostgreSQL был добавлен JSONB тип (бинарный JSON). Данный тип является объединением JSON структуры с возможностью использовать индексы, как у Hstore. JSONB лучше Hstore тем, что есть возможность сохранять вложеную структуру данных (nested) и хранить не только текстовые строки в значениях. Поэтому лучше использовать JSONB, если есть такая возможность. +Начиная с версии 9.4 PostgreSQL был добавлен JSONB тип (бинарный JSON). Данный тип является объединением JSON структуры с возможностью использовать индексы, как у Hstore. JSONB лучше Hstore тем, что есть возможность сохранять вложенную структуру данных (nested) и хранить не только текстовые строки в значениях. Поэтому лучше использовать JSONB, если есть такая возможность. \subsection{Установка и использование} @@ -90,4 +90,4 @@ \subsection{Установка и использование} \subsection{Заключение} -HStore~--- расширение для удобного и индексируемого хранения слабоструктурированых данных в PostgreSQL, если нет возможности использовать версию базы 9.4 или выше, где для данной задачи есть встроенный \href{https://www.postgresql.org/docs/current/static/datatype-json.html}{JSONB} тип данных. +HStore~--- расширение для удобного и индексируемого хранения слабоструктурированных данных в PostgreSQL, если нет возможности использовать версию базы 9.4 или выше, где для данной задачи есть встроенный \href{https://www.postgresql.org/docs/current/static/datatype-json.html}{JSONB} тип данных. diff --git a/extensions/pg_prewarm.tex b/extensions/pg_prewarm.tex index e017aa37..ba4b13ce 100644 --- a/extensions/pg_prewarm.tex +++ b/extensions/pg_prewarm.tex @@ -11,7 +11,7 @@ \subsection{Установка и использование} $ CREATE EXTENSION pg_prewarm; \end{lstlisting} -После уставновки доступна функция \lstinline!pg_prewarm!: +После установки доступна функция \lstinline!pg_prewarm!: \begin{lstlisting}[language=SQL,label=lst:pgprewarm2] $ SELECT pg_prewarm('pgbench_accounts'); diff --git a/extensions/plv8.tex b/extensions/plv8.tex index ebc1ad21..d615744b 100644 --- a/extensions/plv8.tex +++ b/extensions/plv8.tex @@ -115,7 +115,7 @@ \subsection{NoSQL} \item все данные (ключ и значение по ключу) это строка; \end{itemize} -Для хранения данных многие документоориентированные базы данных используют JSON (MongoDB, CouchDB, Couchbase и~т.~д.). Для этого, начиная с PostgreSQL 9.2, добавлен тип данных JSON, а с версии 9.4~--- JSONB. JSON тип можно добавить для PostgreSQL 9.1 и ниже используя PLV8 и \lstinline!DOMAIN!: +Для хранения данных многие документно-ориентированные базы данных используют JSON (MongoDB, CouchDB, Couchbase и~т.~д.). Для этого, начиная с PostgreSQL 9.2, добавлен тип данных JSON, а с версии 9.4~--- JSONB. JSON тип можно добавить для PostgreSQL 9.1 и ниже используя PLV8 и \lstinline!DOMAIN!: \begin{lstlisting}[label=lst:plv8js7,caption=Создание типа JSON] CREATE OR REPLACE FUNCTION diff --git a/extensions/postgres_fdw.tex b/extensions/postgres_fdw.tex index e8d71300..7e6d7908 100644 --- a/extensions/postgres_fdw.tex +++ b/extensions/postgres_fdw.tex @@ -84,6 +84,6 @@ \subsection{Postgres\_fdw и DBLink} PostgreSQL FDW (Foreign Data Wrapper) более новый и рекомендуемый метод подключения к другим источникам данных. Хотя функциональность dblink похожа на FDW, последний является более SQL совместимым и может обеспечивать улучшеную производительность по сравнению с dblink подключениями. Кроме того, в отличии от postgres\_fdw, dblink не способен сделать данные <<только на чтение>>. Это может быть достаточно важно, если требуется обеспечить, чтобы данные в другой базе нельзя было изменять. -В dblink подключения работают только в течение работы сесии и их требуется пересоздавать каждый раз. Postgres\_fdw создает постоянное подключение к другой базе данных. Это может быть как хорошо, так плохо, в зависимости от потребностей. +В dblink подключения работают только в течение работы сессии и их требуется пересоздавать каждый раз. Postgres\_fdw создает постоянное подключение к другой базе данных. Это может быть как хорошо, так плохо, в зависимости от потребностей. -Из положительных сторон dblink можно отнести множество полезных комманд, которые позволяют использовать его для программирования полезного функционала. Также dblink работает в версиях PostgreSQL 8.3 и выше, в то время как postgres\_fdw работает только в PostgreSQL 9.3 и выше (такое может возникнуть, если нет возможности обновить PostgreSQL базу). +Из положительных сторон dblink можно отнести множество полезных команд, которые позволяют использовать его для программирования полезного функционала. Также dblink работает в версиях PostgreSQL 8.3 и выше, в то время как postgres\_fdw работает только в PostgreSQL 9.3 и выше (такое может возникнуть, если нет возможности обновить PostgreSQL базу). diff --git a/partitioning/pg_partman.tex b/partitioning/pg_partman.tex index 1c123dcb..a231ab7c 100644 --- a/partitioning/pg_partman.tex +++ b/partitioning/pg_partman.tex @@ -1,14 +1,14 @@ \section{Pg\_partman} -Поскольку реализация партиционирования реализована неполноценно в PostgreSQL (для управления партициями и данными в них приходится писать функции, тригеры и правила), то существует расширение, которое автоматизирует полностью данный процесс. \href{https://github.com/keithf4/pg\_partman}{PG Partition Manager}, он же pg\_partman, это расширение для создания и управления партициями и партициями партиций (sub-partitoning) в PostgreSQL. Поддерживает партицирование по времени (time-based) или по последованности (serial-based). Для партицирования по диапазону значений (range) существует отдельное расширение \href{https://github.com/moat/range\_partitioning}{Range Partitioning (range\_partitioning)}. +Поскольку реализация партиционирования реализована неполноценно в PostgreSQL (для управления партициями и данными в них приходится писать функции, триггеры и правила), то существует расширение, которое автоматизирует полностью данный процесс. \href{https://github.com/keithf4/pg\_partman}{PG Partition Manager}, он же pg\_partman, это расширение для создания и управления партициями и партициями партиций (sub-partitoning) в PostgreSQL. Поддерживает партицирование по времени (time-based) или по последованности (serial-based). Для партицирования по диапазону значений (range) существует отдельное расширение \href{https://github.com/moat/range\_partitioning}{Range Partitioning (range\_partitioning)}. -Текущая реализация поддерживает только INSERT операции, которые перенаправляют данные в нужную партицию. UPDATE операции, которые будут перемещать данные из одной партиции в другую, не поддерживаются. При попытке вставить данные, на которые нет партиции, pg\_partman перемещает их в <<мастер>> (родительскую) таблицу. Данный вариант предпочтительнее, чем создавать автоматически новые партиции, поскольку это может привести к созданию десятков или сотен ненужных дочерных таблиц из-за ошибки в самих данных. Функция \lstinline!check_parent! позволяет проверить попадение подобных данных в родительскую таблицу и решить, что с ними требуется делать (удалить или использовать \lstinline!partition_data_time/partition_data_id! для создания и переноса этих данных в партиции). +Текущая реализация поддерживает только INSERT операции, которые перенаправляют данные в нужную партицию. UPDATE операции, которые будут перемещать данные из одной партиции в другую, не поддерживаются. При попытке вставить данные, на которые нет партиции, pg\_partman перемещает их в <<мастер>> (родительскую) таблицу. Данный вариант предпочтительнее, чем создавать автоматически новые партиции, поскольку это может привести к созданию десятков или сотен ненужных дочерних таблиц из-за ошибки в самих данных. Функция \lstinline!check_parent! позволяет проверить попадение подобных данных в родительскую таблицу и решить, что с ними требуется делать (удалить или использовать \lstinline!partition_data_time/partition_data_id! для создания и переноса этих данных в партиции). Данное расширение использует большинство атрибутов родительской таблицы для создания партиций: индексы, внешние ключи (опционально), tablespace, constraints, privileges и ownership. Под такое условие попадают OID и UNLOGGED таблицы. Партициями партиций (sub-partitoning) поддерживаются разных уровней: time->time, id->id, time->id и id->time. Нет лимитов на создание таких партиций, но стоит помнить, что большое число партиций влияет на производительность родительской таблицы. Если размер партиций станет слишком большим, то придется увеличивать \lstinline!max_locks_per_transaction! параметр для базы данных (64 по умолчанию). -В PostgreSQL 9.4 появилась возможность создания пользовательских фоновых воркеров и динамически загружать их во время работы базы. Благодаря этому в pg\_partman есть собственный фоновый воркер, задача которого запускать \lstinline!run_maintenance! функцию каждый заданный промежуток времени. Если у Вас версия PostgreSQL ниже 9.4, то придется воспользоватся внешним планировщиком для выполнения данной функции (например cron). Задача данной функции - проверять и автоматически создавать партиции и опционально чистить старые. +В PostgreSQL 9.4 появилась возможность создания пользовательских фоновых воркеров и динамически загружать их во время работы базы. Благодаря этому в pg\_partman есть собственный фоновый воркер, задача которого запускать \lstinline!run_maintenance! функцию каждый заданный промежуток времени. Если у Вас версия PostgreSQL ниже 9.4, то придется воспользоваться внешним планировщиком для выполнения данной функции (например cron). Задача данной функции - проверять и автоматически создавать партиции и опционально чистить старые. \subsection{Пример использования} diff --git a/partitioning/pgslice.tex b/partitioning/pgslice.tex index 08822bd9..619a5d3b 100644 --- a/partitioning/pgslice.tex +++ b/partitioning/pgslice.tex @@ -1,6 +1,6 @@ \section{Pgslice} -\href{https://github.com/ankane/pgslice}{Pgslice}~--- утилита для создания и управления партициями в PostgreSQL. Утилита разбивает на <<куски>> как новую, так и существующию таблицу с данными c нулевым временем простоя (<>). +\href{https://github.com/ankane/pgslice}{Pgslice}~--- утилита для создания и управления партициями в PostgreSQL. Утилита разбивает на <<куски>> как новую, так и существующую таблицу с данными c нулевым временем простоя (<>). Утилита написана на \href{https://www.ruby-lang.org}{Ruby}, поэтому потребуется сначала установить его. После этого устанавливаем pgslice через rubygems (многие ruby разработчики используют \href{http://bundler.io/}{bundler} для лучшего управления зависимостями, но в этой главе это не рассматривается): diff --git a/performance/beginning.tex b/performance/beginning.tex index c07e928e..71048a43 100644 --- a/performance/beginning.tex +++ b/performance/beginning.tex @@ -42,8 +42,8 @@ \subsection{Используйте актуальную версию серве \item В версии 9.2 <<каскадная репликация из коробки>>, сканирование по индексу, JSON тип данных, типы данных на диапазоны, сортировка в памяти улучшена на 25\%, ускорена команда COPY; \item В версии 9.3 materialized view, доступные на запись внешние таблицы, переход с использования SysV shared memory на POSIX shared memory и mmap, cокращено время распространения реплик, а также значительно ускорена передача управления от запасного сервера к первичному, увеличена производительность и улучшена система блокировок для внешних ключей; \item В версии 9.4 появился новый тип поля JSONB (бинарный JSON с поддержкой индексов), логическое декодирование для репликации, GIN индекс в 2 раза меньше по размеру и в 3 раза быстрее, неблокируюшие обновление materialized view, поддержка Linux Huge Pages; - \item В версии 9.5 добавленна поддержка UPSERT, Row Level Security, CUBE, ROLLUP, GROUPING SETS функции, TABLESAMPLE, BRIN индекс, ускорена скорость работы индексов для текстовых и цифровых полей; - \item В версии 9.6 добавленна поддержка параллелизации некоторых запросов, что позволяет использование несколько ядер (CPU core) на сервере, чтобы возвращать результаты запроса быстрее, полнотекстовый поиск поддерживает фразы, новая опция <> для синхронной репликации, которая позволяет дождаться, пока запрос завершится на слейве; + \item В версии 9.5 добавлена поддержка UPSERT, Row Level Security, CUBE, ROLLUP, GROUPING SETS функции, TABLESAMPLE, BRIN индекс, ускорена скорость работы индексов для текстовых и цифровых полей; + \item В версии 9.6 добавлена поддержка параллелизации некоторых запросов, что позволяет использование несколько ядер (CPU core) на сервере, чтобы возвращать результаты запроса быстрее, полнотекстовый поиск поддерживает фразы, новая опция <> для синхронной репликации, которая позволяет дождаться, пока запрос завершится на слейве; \end{itemize} Следует также отметить, что большая часть изложенного в статье материала относится к версии сервера не ниже 9.0. diff --git a/performance/settings.tex b/performance/settings.tex index 0ac447c0..82c65a8a 100644 --- a/performance/settings.tex +++ b/performance/settings.tex @@ -72,7 +72,7 @@ \subsubsection{Большие страницы: huge\_pages} После перезапуска базы с параметром \lstinline!try! потребуется включить поддержку больших страниц в системе (по умолчанию они не задействованы). Расчет страниц приблизительный и здесь следует опираться на то, сколько памяти вы готовы выделить под нужды СУБД. Отмечу, что значение измеряется в страницах размером 2Mb, если вы хотите выделить 16GB, то это будет 8000 страниц. -Официальная документация предлагает опираться на значение \lstinline!VmPeak! из status файла, который размещен в \lstinline!/proc/PID/! директории, соответствующей номеру процесса postmaster. \lstinline!VmPeak! как следует из названия это пиковое значение использования виртуальной памяти. Этот вариант позволяет определить минимальную планку, от которой следует отталкиваться, но на мой вгляд такой способ определения тоже носит случайный характер. +Официальная документация предлагает опираться на значение \lstinline!VmPeak! из status файла, который размещен в \lstinline!/proc/PID/! директории, соответствующей номеру процесса postmaster. \lstinline!VmPeak! как следует из названия это пиковое значение использования виртуальной памяти. Этот вариант позволяет определить минимальную планку, от которой следует отталкиваться, но на мой взгляд такой способ определения тоже носит случайный характер. \begin{lstlisting}[language=Bash,label=lst:settings_hugepages2,caption=Включаем поддержку huge pages в системе] $ head -1 /var/lib/pgsql/9.5/data/postmaster.pid @@ -143,7 +143,7 @@ \subsubsection{fsync, synchronous\_commit и стоит ли их трогать Для увеличения производительности наиболее радикальное из возможных решений~--- выставить значение <> параметру \lstinline!fsync!. При этом записи в журнале транзакций не будут принудительно сбрасываться на диск, что даст большой прирост скорости записи. Учтите: вы жертвуете надёжностью, в случае сбоя целостность базы будет нарушена, и её придётся восстанавливать из резервной копии! Использовать этот параметр рекомендуется лишь в том случае, если вы всецело доверяете своему <<железу>> и своему источнику бесперебойного питания. Ну или если данные в базе не представляют для вас особой ценности. -Параметр \lstinline!synchronous_commit! определяет нужно ли ждать WAL записи на диск перед возвратом успешного завершения транзакции для подключенного клиента. По умолчанию и для безопасности данный параметр установлен в <> (включен). При выключении данного параметра (<>) может существовать задержка между моментом, когда клиенту будет сообщенно об успехе транзакции и когда та самая транзакция действительно гарантированно и безопасно записана на диск (максимальная задержка~--- \lstinline!wal_writer_delay * 3!). В отличие от \lstinline!fsync!, отключение этого параметра не создает риск краха базы данных: данные могут быть потеряны (последний набор транзакций), но базу данных не придется восстанавливать после сбоя из бэкапа. Так что \lstinline!synchronous_commit! может быть полезной альтернативой, когда производительность важнее, чем точная уверенность в согласовании данных (данный режим можно назвать <<режимом MongoDB>>: изначально все клиенты для MongoDB не проверяли успешность записи данных в базу и за счет этого достигалась хорошая скорость для бенчмарков). +Параметр \lstinline!synchronous_commit! определяет нужно ли ждать WAL записи на диск перед возвратом успешного завершения транзакции для подключенного клиента. По умолчанию и для безопасности данный параметр установлен в <> (включен). При выключении данного параметра (<>) может существовать задержка между моментом, когда клиенту будет сообщено об успехе транзакции и когда та самая транзакция действительно гарантированно и безопасно записана на диск (максимальная задержка~--- \lstinline!wal_writer_delay * 3!). В отличие от \lstinline!fsync!, отключение этого параметра не создает риск краха базы данных: данные могут быть потеряны (последний набор транзакций), но базу данных не придется восстанавливать после сбоя из бэкапа. Так что \lstinline!synchronous_commit! может быть полезной альтернативой, когда производительность важнее, чем точная уверенность в согласовании данных (данный режим можно назвать <<режимом MongoDB>>: изначально все клиенты для MongoDB не проверяли успешность записи данных в базу и за счет этого достигалась хорошая скорость для бенчмарков). \subsubsection{Прочие настройки} diff --git a/postgresql_backup.tex b/postgresql_backup.tex index 6ac17cd5..1bbd8888 100644 --- a/postgresql_backup.tex +++ b/postgresql_backup.tex @@ -137,7 +137,7 @@ \section{Бэкап уровня файловой системы} \item Не получится восстановить только определенные данные с такого бэкапа; \end{itemize} -Как альтернатива, можно делать снимки (snapshot) файлов системы (папки с файлами PostgreSQL). В таком случае останавливать PostgreSQL не требуется. Однако, резервная копия, созданная таким образом, сохраняет файлы базы данных в состоянии, как если бы сервер базы данных был неправильно остановлен. Поэтому при запуске PostgreSQL из резервной копии, он будет думать, что предыдущий экземпляр сервера вышел из строя и восстановит данные в соотвествии с данными журнала WAL. Это не проблема, просто надо знать про это (и не забыть включить WAL файлы в резервную копию). Также, если файловая система PostgreSQL распределена по разным файловым системам, то такой метод бэкапа будет очень ненадежным~--- снимки файлов системы должны быть сделаны одновременно. Почитайте документацию файловой системы очень внимательно, прежде чем доверять снимкам файлов системы в таких ситуациях. +Как альтернатива, можно делать снимки (snapshot) файлов системы (папки с файлами PostgreSQL). В таком случае останавливать PostgreSQL не требуется. Однако, резервная копия, созданная таким образом, сохраняет файлы базы данных в состоянии, как если бы сервер базы данных был неправильно остановлен. Поэтому при запуске PostgreSQL из резервной копии, он будет думать, что предыдущий экземпляр сервера вышел из строя и восстановит данные в соответствии с данными журнала WAL. Это не проблема, просто надо знать про это (и не забыть включить WAL файлы в резервную копию). Также, если файловая система PostgreSQL распределена по разным файловым системам, то такой метод бэкапа будет очень ненадежным~--- снимки файлов системы должны быть сделаны одновременно. Почитайте документацию файловой системы очень внимательно, прежде чем доверять снимкам файлов системы в таких ситуациях. Также возможен вариант с использованием \lstinline!rsync! утилиты. Первым запуском rsync мы копируем основные файлы с директории PostgreSQL (PostgreSQL при этом продолжает работу). После этого мы останавливаем PostgreSQL и запускаем повторно \lstinline!rsync!. Второй запуск \lstinline!rsync! пройдет гораздо быстрее, чем первый, потому что будет передавать относительно небольшой размер данных, и конечный результат будет соответствовать остановленной СУБД. Этот метод позволяет делать бэкап уровня файловой системы с минимальным временем простоя. diff --git a/postgresql_indexes.tex b/postgresql_indexes.tex index bbbfba74..f2cb5158 100644 --- a/postgresql_indexes.tex +++ b/postgresql_indexes.tex @@ -40,7 +40,7 @@ \subsection{B-Tree} B-Tree для индексов отличается от представленной на Википедии~--- есть дублированные данных в промежуточных блоках. Для i-ой записи в блоке сохраняется не значение, которое больше максимума i-го поддерева, и меньше минимума (i+1) поддерева, а максимум i-го поддерева. Различия проистекают из того, что википедия приводит пример B-Tree для множества, а нам нужен ассоциативный массив. -В индексном B-Tree значения и RowId размещаются совместно на нижнем слое дерева. Каждый узел дерева представляет из себя одну страницу (page) в некотором формате. В начале страницы всегда идёт некоторый заголовок. Для корневого и промежуточного узла в страницах хранятся пары (Значение, Номер страницы). Для листовых~--- пары (Значение ,RowId) либо (Значение, Список RowId) (в зависимости от свойств значения~--- уникально или нет). B-Tree деревья имеют крайне маленькую высоту~--- порядка $H = \log_m{N}$, где m~--- количество записей в блоке, N~--- количество элементов. B-Tree деревья являются упорядоченными~--- все элементы в любой странице (блоке) дерева лежат последовательно. Предыдущие два свойства позволяют крайне эффективно производить поиск~--- начиная с первой страницы, половинным делением (binary search) выделяются дети, в которых лежат границы поиска. Таким образом, прочитав всего H, 2H страниц мы находим искомый диапозон. Важным нюансом является также факт, что страницы в листьях связаны в односвязный либо двусвязный список - это означает, что, выполнив поиск, мы можем дальше просто последовательно читать страницы, и эффективность чтения большего объёма данных (длинного диапазона) сравнима с эффективностью чтения данных из таблицы. +В индексном B-Tree значения и RowId размещаются совместно на нижнем слое дерева. Каждый узел дерева представляет из себя одну страницу (page) в некотором формате. В начале страницы всегда идёт некоторый заголовок. Для корневого и промежуточного узла в страницах хранятся пары (Значение, Номер страницы). Для листовых~--- пары (Значение ,RowId) либо (Значение, Список RowId) (в зависимости от свойств значения~--- уникально или нет). B-Tree деревья имеют крайне маленькую высоту~--- порядка $H = \log_m{N}$, где m~--- количество записей в блоке, N~--- количество элементов. B-Tree деревья являются упорядоченными~--- все элементы в любой странице (блоке) дерева лежат последовательно. Предыдущие два свойства позволяют крайне эффективно производить поиск~--- начиная с первой страницы, половинным делением (binary search) выделяются дети, в которых лежат границы поиска. Таким образом, прочитав всего H, 2H страниц мы находим искомый диапазон. Важным нюансом является также факт, что страницы в листьях связаны в односвязный либо двусвязный список - это означает, что, выполнив поиск, мы можем дальше просто последовательно читать страницы, и эффективность чтения большего объёма данных (длинного диапазона) сравнима с эффективностью чтения данных из таблицы. Сильные стороны B-Tree индексов: @@ -48,7 +48,7 @@ \subsection{B-Tree} \item сохраняют сортированность данных; \item поддерживают поиск по унарным и бинарным предикатам (\lstinline!c and f!) за O($\log_m{N}$), где m~--- количество записей в блоке, N~--- количество элементов; \item позволяют не сканируя последовательность данных целиком оценить cardinality (количество записей) для всего индекса (а следовательно таблицы), диапазона, причём с произвольной точностью. Посмотрели корневую страницу~--- получили одну точность. Посмотрели следующий уровень дерева~--- получили точность получше. Просмотрели дерево до корня~--- получили точное число записей; - \item самобалансируемый, для внесения изменения не требуется полного перестроения, происходит не более O($\log_m{N}$) дейстий, где m~--- количество записей в блоке, N~--- количество элементов; + \item самобалансируемый, для внесения изменения не требуется полного перестроения, происходит не более O($\log_m{N}$) действий, где m~--- количество записей в блоке, N~--- количество элементов; \end{itemize} Слабые стороны B-Tree индексов: @@ -91,7 +91,7 @@ \subsection{R-Tree} \subsection{Hash индекс} -Hash индекс по сути является ассоциативным хеш-контейнером. Хеш-контейнер~--- это массив из разряженных значений. Адресуются отдельные элементы этого массива некоторой хеш-функцией которая отображает каждое значение в некоторое целое число. Т.~е. результат хеш-функции является порядковым номером элемента в массиве. Элементы массива в хеш-конейтнере называются бакетами (bucket). Обычно один бакет~--- одна страница. Хеш-функция отображает более мощное множество в менее мощное, возникают так называемые коллизии~--- ситуация, когда одному значению хеш-функции соответствует несколько разных значений. В бакете хранятся значения, образующие коллизию. Разрешение коллизий происходит посредством поиска среди значений, сохранённых в бакете. +Hash индекс по сути является ассоциативным хеш-контейнером. Хеш-контейнер~--- это массив из разряженных значений. Адресуются отдельные элементы этого массива некоторой хеш-функцией которая отображает каждое значение в некоторое целое число. Т.~е. результат хеш-функции является порядковым номером элемента в массиве. Элементы массива в хеш-контейнере называются бакетами (bucket). Обычно один бакет~--- одна страница. Хеш-функция отображает более мощное множество в менее мощное, возникают так называемые коллизии~--- ситуация, когда одному значению хеш-функции соответствует несколько разных значений. В бакете хранятся значения, образующие коллизию. Разрешение коллизий происходит посредством поиска среди значений, сохранённых в бакете. \begin{figure}[ht!] \center{\includegraphics[width=1\textwidth]{hash_index.pdf}} @@ -241,4 +241,4 @@ \subsection{Уникальный индекс (unique index)} \subsection{Индекс нескольких столбцов (multi-column index)} -В PostgreSQL возможно создавать индексы на несколько столбцов, но нам главное нужно понять когда имеет смысл создавать такой индекс, поскольку планировщик запросов PostgreSQL может комбинировать и использовать несколько индексов в запросе путем создания битового индекса (<<\ref{sec:indexes-bitmap-index}~\nameref{sec:indexes-bitmap-index}>>). Можно, конечно, создать индексы, которые охватят все возможные запросы, но за это придется платить производительностью (индексы нужно перестраивать при запросах на модификацию данных). Нужно также помнить, что индексы на несколько столбцов могут использоваться только запросами, которые ссылаются на эти столбцы в индексе в том же порядке. Индекс по столбцам \lstinline!(a, b)! может быть использован в запросах, которые содержат \lstinline!a = x and b = y! или \lstinline!a = x!, но не будет использоваться в запросе вида \lstinline!b = y!. Если это подходит под запросы вашего приложения, то данный индекс может быть полезен. В таком случае создание индекса на поле \lstinline!a! было бы излишним. Индекс нескольких столбцов с указанием уникальности (\lstinline!unique!) может быть также полезен для сохранения целосности данных (т.~е. когда набор данных в этих стобцах должен быть уникальным). +В PostgreSQL возможно создавать индексы на несколько столбцов, но нам главное нужно понять когда имеет смысл создавать такой индекс, поскольку планировщик запросов PostgreSQL может комбинировать и использовать несколько индексов в запросе путем создания битового индекса (<<\ref{sec:indexes-bitmap-index}~\nameref{sec:indexes-bitmap-index}>>). Можно, конечно, создать индексы, которые охватят все возможные запросы, но за это придется платить производительностью (индексы нужно перестраивать при запросах на модификацию данных). Нужно также помнить, что индексы на несколько столбцов могут использоваться только запросами, которые ссылаются на эти столбцы в индексе в том же порядке. Индекс по столбцам \lstinline!(a, b)! может быть использован в запросах, которые содержат \lstinline!a = x and b = y! или \lstinline!a = x!, но не будет использоваться в запросе вида \lstinline!b = y!. Если это подходит под запросы вашего приложения, то данный индекс может быть полезен. В таком случае создание индекса на поле \lstinline!a! было бы излишним. Индекс нескольких столбцов с указанием уникальности (\lstinline!unique!) может быть также полезен для сохранения целостности данных (т.~е. когда набор данных в этих стобцах должен быть уникальным). diff --git a/postgresql_pgpool.tex b/postgresql_pgpool.tex index 4d96ecd0..c712a9f8 100644 --- a/postgresql_pgpool.tex +++ b/postgresql_pgpool.tex @@ -441,7 +441,7 @@ \subsection{Streaming Replication (Потоковая репликация)} failover_command = '/path_to_script/failover_stream.sh %d %H /tmp/trigger_file' \end{lstlisting} -где \lstinline!/tmp/trigger_file!~--- триггер файл, указаный в конфиге \lstinline!recovery.conf!. Теперь, если мастер СУБД упадет, слейв будет переключен из режима восстановления в обычный и сможет принимать запросы на запись. +где \lstinline!/tmp/trigger_file!~--- триггер файл, указанный в конфиге \lstinline!recovery.conf!. Теперь, если мастер СУБД упадет, слейв будет переключен из режима восстановления в обычный и сможет принимать запросы на запись. @@ -512,7 +512,7 @@ \subsection{Streaming Replication (Потоковая репликация)} \item Оставляем \lstinline!recovery_2nd_stage_command! пустым. После успешного выполнения первого этапа онлайн восстановления, разницу в данных, что успели записаться во время работы скрипта \lstinline!basebackup.sh!, слейв инстанс заберет через WAL файлы с мастера; - \item Устанавливаем C и SQL функции для работы онлайн востановления на каждый инстанс СУБД: + \item Устанавливаем C и SQL функции для работы онлайн восстановления на каждый инстанс СУБД: \begin{lstlisting}[language=Bash,label=lst:pgpool46,caption=Устанавливаем C и SQL функции] $ cd pgpool-II-x.x.x/sql/pgpool-recovery diff --git a/postgresql_replication.tex b/postgresql_replication.tex index a28b67b2..0a511a32 100644 --- a/postgresql_replication.tex +++ b/postgresql_replication.tex @@ -2,7 +2,7 @@ \chapter{Репликация} \begin{epigraphs} \qitem{Когда решаете проблему, ни о чем не беспокойтесь. -Вот когда вы её решите, тогда и наступит время беспокоиться}{Ричард Филлипс Фейман} +Вот когда вы её решите, тогда и наступит время беспокоиться}{Ричард Филлипс Фейнман} \end{epigraphs} \section{Введение} @@ -60,4 +60,4 @@ \section{Заключение} Репликация~--- одна из важнейших частей крупных приложений, которые работают на PostgreSQL. Она помогает распределять нагрузку на базу данных, делать фоновый бэкап одной из копий без нагрузки на центральный сервер, создавать отдельный сервер для логирования или аналитики, прочее. -В главе было рассмотрено несколько видов репликации PostgreSQL. Нельзя четко сказать какая лучше всех. Потоковая репликация~--- один из самых лучших вариантов для поддержки идентичных кластеров баз данных. Slony-I~--- громоздкая и сложная в настройке система, но имеющая в своем арсенале множество функций, таких как отказоустойчивости (failover) и переключение между серверами (switchover). В тоже время Londiste имея в своем арсенале подобный функционал, может похвастатся еще компактностью и простой в установке. Bucardo~--- система которая может быть или master-master, или master-slave репликацией. +В главе было рассмотрено несколько видов репликации PostgreSQL. Нельзя четко сказать какая лучше всех. Потоковая репликация~--- один из самых лучших вариантов для поддержки идентичных кластеров баз данных. Slony-I~--- громоздкая и сложная в настройке система, но имеющая в своем арсенале множество функций, таких как отказоустойчивости (failover) и переключение между серверами (switchover). В тоже время Londiste имея в своем арсенале подобный функционал, может похвастаться еще компактностью и простой в установке. Bucardo~--- система которая может быть или master-master, или master-slave репликацией. diff --git a/replication/bdr.tex b/replication/bdr.tex index a21bb733..e8abb233 100644 --- a/replication/bdr.tex +++ b/replication/bdr.tex @@ -1,7 +1,7 @@ \section{PostgreSQL Bi-Directional Replication (BDR)} \label{sec:bdr} -\href{https://2ndquadrant.com/en/resources/bdr/}{BDR (Bi-Directional Replication)} это новая функциональность добавленая в ядро PostgreSQL которая предоставляет расширенные средства для репликации. На данный момент это реализовано в виде небольшого патча и модуля для 9.4 версии. Заявлено что полностью будет только в PostgreSQL 9.6 (разработчики решили не заниматься поддержкой патча для 9.5, а сосредоточиться на добавление патчей в сам PostgreSQL). BDR позволяет создавать географически распределенные асинхронные мульти-мастер конфигурации используя для этого встроенную логическую потоковую репликацию LLSR (Logical Log Streaming Replication). +\href{https://2ndquadrant.com/en/resources/bdr/}{BDR (Bi-Directional Replication)} это новая функциональность добавленная в ядро PostgreSQL которая предоставляет расширенные средства для репликации. На данный момент это реализовано в виде небольшого патча и модуля для 9.4 версии. Заявлено что полностью будет только в PostgreSQL 9.6 (разработчики решили не заниматься поддержкой патча для 9.5, а сосредоточиться на добавление патчей в сам PostgreSQL). BDR позволяет создавать географически распределенные асинхронные мульти-мастер конфигурации используя для этого встроенную логическую потоковую репликацию LLSR (Logical Log Streaming Replication). BDR не является инструментом для кластеризации, т.к. здесь нет каких-либо глобальных менеджеров блокировок или координаторов транзакций. Каждый узел не зависит от других, что было бы невозможно в случае использования менеджеров блокировки. Каждый из узлов содержит локальную копию данных идентичную данным на других узлах. Запросы также выполняются только локально. При этом каждый из узлов внутренне консистентен в любое время, целиком же группа серверов является согласованной в конечном счете (eventually consistent). Уникальность BDR заключается в том что она непохожа ни на встроенную потоковую репликацию, ни на существующие trigger-based решения (Londiste, Slony, Bucardo). @@ -11,7 +11,7 @@ \section{PostgreSQL Bi-Directional Replication (BDR)} \item Все изменения данных вызываемые \lstinline!INSERT/DELETE/UPDATE! реплицируются (\lstinline!TRUNCATE! на момент написания статьи пока не реализован); \item Большинство операции изменения схемы (DDL) реплицируются успешно. Неподдерживаемые DDL фиксируются модулем репликации и отклоняются с выдачей ошибкой (на момент написания не работал \lstinline!CREATE TABLE ... AS!); \item Определения таблиц, типов, расширений и~т.~п. должны быть идентичными между upstream и downstream мастерами; - \item Действия которые отражаются в WAL, но непредставляются в виде логических изменений не реплицируются на другой узел (запись полных страниц, вакуумация таблиц и~т.~п.). Таким образом логическая потоковая репликация (LLSR) избавлена от некоторой части накладных расходов которые присутствуют в физической потоковой репликации PLSR (тем не менее это не означает что LLSR требуется меньшая пропускная способность сети чем для PLSR); + \item Действия которые отражаются в WAL, но не представляются в виде логических изменений не реплицируются на другой узел (запись полных страниц, вакуумация таблиц и~т.~п.). Таким образом логическая потоковая репликация (LLSR) избавлена от некоторой части накладных расходов которые присутствуют в физической потоковой репликации PLSR (тем не менее это не означает что LLSR требуется меньшая пропускная способность сети чем для PLSR); \end{itemize} Небольшое примечание: временная остановка репликации осуществляется выключением downstream мастера. Однако стоит отметить что остановленная реплика приводит к тому что upstream мастер продолжит накапливать WAL журналы что в свою очередь может привести к неконтролируемому расходу пространства на диске. Поэтому крайне не рекомендуется надолго выключать реплику. Удаление реплики навсегда осуществляется через удаление конфигурации BDR на downstream сервере с последующим перезапуском downstream мастера. Затем нужно удалить соответствующий слот репликации на upstream мастере с помощью функции \lstinline!pg_drop_replication_slot('slotname')!. Доступные слоты можно просмотреть с помощью функции \lstinline!pg_get_replication_slots!. diff --git a/replication/bucardo.tex b/replication/bucardo.tex index db61f0d8..b38b8ab5 100644 --- a/replication/bucardo.tex +++ b/replication/bucardo.tex @@ -192,7 +192,7 @@ \subsubsection{Просмотр значений конфигурации} \subsubsection{Изменения значений конфигурации} -\begin{lstlisting}[language=Bash,label=lst:bucardo14,caption=Изменения значений конфигурациии] +\begin{lstlisting}[language=Bash,label=lst:bucardo14,caption=Изменения значений конфигурации] $ bucardo set name=value \end{lstlisting} @@ -247,7 +247,7 @@ \subsection{Репликация в другие типы баз данных} Added table "public.pgbench_tellers" \end{lstlisting} -После перезапуска Bucardo данные с PostgreSQL таблиц начнуть реплицироватся в Redis: +После перезапуска Bucardo данные с PostgreSQL таблиц начнут реплицироваться в Redis: \begin{lstlisting}[language=Bash,label=lst:bucardo-redis5,caption=Репликация в redis] $ pgbench -T 10 -c 5 simple_database diff --git a/replication/londiste.tex b/replication/londiste.tex index c471fa57..c75a7457 100644 --- a/replication/londiste.tex +++ b/replication/londiste.tex @@ -25,7 +25,7 @@ \subsection{Установка} % sudo aptitude install skytools \end{lstlisting} -В некоторых системнах пакет может содержатся версия 2.x, которая не поддерживает каскадную репликацию, отказоустойчивость(failover) и переключение между серверами (switchover). По этой причине она не будет расматриваться. Скачать самую последнюю версию пакета можно с \href{http://pgfoundry.org/projects/skytools}{официального сайта}. На момент написания главы последняя версия была 3.2. Начнем установку: +В некоторых системах может содержаться пакет версии 2.x, который не поддерживает каскадную репликацию, отказоустойчивость(failover) и переключение между серверами (switchover). По этой причине он не будет рассматриваться. Скачать самую последнюю версию пакета можно с \href{http://pgfoundry.org/projects/skytools}{официального сайта}. На момент написания главы последняя версия была 3.2. Начнем установку: \begin{lstlisting}[label=lst:londiste2,caption=Установка] $ wget http://pgfoundry.org/frs/download.php/3622/skytools-3.2.tar.gz @@ -133,7 +133,7 @@ \subsubsection{Конфигурация репликаторов} INFO {standby: 1} \end{lstlisting} -Если нужно перегрузить демон (например при изменении конфигурации), то можно воспользоватся параметром \lstinline!-r!: +Если нужно перегрузить демон (например при изменении конфигурации), то можно воспользоваться параметром \lstinline!-r!: \begin{lstlisting}[label=lst:londiste-replica4,caption=Перегрузка демона] $ londiste3 /etc/skytools/master-londiste.ini -r @@ -261,7 +261,7 @@ \subsubsection{Создаём конфигурацию для PgQ ticker} $ londiste3 /etc/skytools/slave1-londiste.ini add-table --all --create-full \end{lstlisting} -В данном примере используется параметр \lstinline!--all!, который означает все таблицы, но вместо него вы можете перечислить список конкретных таблиц, если не хотите реплицировать все. Если имена таблиц отличаются на master и slave, то можно использовать \lstinline!--dest-table! параметр при добавлении таблиц на slave базе. Также, если вы не перенесли струкруру таблиц заранее с master на slave базы, то это можно сделать автоматически через \lstinline!--create! параметр (или \lstinline!--create-full!, если нужно перенести полностью всю схему таблицы). +В данном примере используется параметр \lstinline!--all!, который означает все таблицы, но вместо него вы можете перечислить список конкретных таблиц, если не хотите реплицировать все. Если имена таблиц отличаются на master и slave, то можно использовать \lstinline!--dest-table! параметр при добавлении таблиц на slave базе. Также, если вы не перенесли структуру таблиц заранее с master на slave базы, то это можно сделать автоматически через \lstinline!--create! параметр (или \lstinline!--create-full!, если нужно перенести полностью всю схему таблицы). Подобным образом добавляем последовательности (\lstinline!sequences!) для репликации: @@ -298,7 +298,7 @@ \subsubsection{Создаём конфигурацию для PgQ ticker} \item z - количество таблиц в состоянии ignored (table not replicated locally), у master должно быть 0, а у slave базах это количество таблиц, которые не добавлены для репликации с мастера (т.~е. master отдает на репликацию эту таблицу, но slave их просто не забирает). \end{itemize} -Через небольшой интервал времени все таблицы должны синхронизироватся: +Через небольшой интервал времени все таблицы должны синхронизироваться: \begin{lstlisting}[label=lst:londiste-replica16,caption=Статус кластера] $ londiste3 /etc/skytools/master-londiste.ini status @@ -335,7 +335,7 @@ \subsubsection{Создаём конфигурацию для PgQ ticker} \subsubsection{Проверка} -Для проверки будем использовать \lstinline!pgbench! утилиту. Запустим добавление данных в таблицу и смотрим в логи одновлеменно: +Для проверки будем использовать \lstinline!pgbench! утилиту. Запустим добавление данных в таблицу и смотрим в логи одновременно: \begin{lstlisting}[label=lst:londiste-check1,caption=Проверка] $ pgbench -T 10 -c 5 l3simple @@ -466,7 +466,7 @@ \subsubsection{Каскадная репликация} Lag: 12s, Tick: 56 \end{lstlisting} -Также топологию можно менять с сторони репликатора через команду \lstinline!takeover!: +Также топологию можно менять с стороны репликатора через команду \lstinline!takeover!: \begin{lstlisting}[label=lst:londiste-cascade8,caption=Изменяем топологию] $ londiste3 /etc/skytools/slave3-londiste.ini takeover slave4-node diff --git a/replication/pglogical.tex b/replication/pglogical.tex index 0f63dff7..e8c2c69b 100644 --- a/replication/pglogical.tex +++ b/replication/pglogical.tex @@ -51,7 +51,7 @@ \subsection{Установка и настройка} # property available in PostgreSQL 9.5+ \end{lstlisting} -В \lstinline!pg_hba.conf! нужно разрешить replication соеденения с локального хоста для пользователя с привилегией репликации. После перезапуска базы нужно активировать расширение на всех нодах: +В \lstinline!pg_hba.conf! нужно разрешить replication соединения с локального хоста для пользователя с привилегией репликации. После перезапуска базы нужно активировать расширение на всех нодах: \begin{lstlisting}[label=lst:pglogical3,language=SQL,caption=Активируем расширение] CREATE EXTENSION pglogical; diff --git a/replication/slony.tex b/replication/slony.tex index 6017c7ce..c7a9b9ff 100644 --- a/replication/slony.tex +++ b/replication/slony.tex @@ -383,7 +383,7 @@ \subsubsection{Ошибка при добавлении узла в систем \subsubsection{Что делать если репликация со временем начинает тормозить} -В процессе эксплуатации может наблюдатся как со временем растёт нагрузка на master-сервере, в списке активных бекендов~--- постоянные SELECT-ы со слейвов. В \lstinline!pg_stat_activity! видны примерно такие запросы: +В процессе эксплуатации может наблюдаться как со временем растёт нагрузка на master-сервере, в списке активных бекендов~--- постоянные SELECT-ы со слейвов. В \lstinline!pg_stat_activity! видны примерно такие запросы: \begin{lstlisting}[label=lst:slony19,caption=Устранение неисправностей] select ev_origin, ev_seqno, ev_timestamp, ev_minxid, ev_maxxid, ev_xip, diff --git a/replication/streaming.tex b/replication/streaming.tex index cef96969..ee0d909f 100644 --- a/replication/streaming.tex +++ b/replication/streaming.tex @@ -41,9 +41,9 @@ \subsubsection{Предварительная настройка} $ su postgres \end{lstlisting} -Генерим RSA-ключ для обеспечения аутентификации в условиях отсутствия возможности использовать пароль: +Генерируем RSA-ключ для обеспечения аутентификации в условиях отсутствия возможности использовать пароль: -\begin{lstlisting}[label=lst:streaming3,caption=Генерим RSA-ключ] +\begin{lstlisting}[label=lst:streaming3,caption=Генерируем RSA-ключ] $ ssh-keygen -t rsa -P "" Generating public/private rsa key pair. Enter file in which to save the key (/var/lib/postgresql/.ssh/id_rsa): @@ -72,7 +72,7 @@ \subsubsection{Предварительная настройка} $ $/etc/init.d/sshd start \end{lstlisting} -После успешно проделаной операции скопируйте \lstinline!$HOME/.ssh! на \lstinline!slavedb!. Теперь мы должны иметь возможность без пароля заходить с мастера на слейв и со слейва на мастер через ssh. +После успешно проделанной операции скопируйте \lstinline!$HOME/.ssh! на \lstinline!slavedb!. Теперь мы должны иметь возможность без пароля заходить с мастера на слейв и со слейва на мастер через ssh. Также отредактируем \lstinline!pg_hba.conf! на мастере и слейве, разрешив им друг к другу доступ без пароля (тут добавляется роль \lstinline!replication!): @@ -168,7 +168,7 @@ \subsubsection{Настройка слейва} $ psql -c "SELECT pg_stop_backup()" \end{lstlisting} -Для версии PostgreSQL 9.1+ можно воспользоватся командой \lstinline!pg_basebackup! (копирует базу на \lstinline!slavedb! подобным образом): +Для версии PostgreSQL 9.1+ можно воспользоваться командой \lstinline!pg_basebackup! (копирует базу на \lstinline!slavedb! подобным образом): \begin{lstlisting}[label=lst:streaming122,caption=Выполняем на слейве] $ pg_basebackup -R -D /srv/pgsql/standby --host=192.168.0.10 --port=5432 @@ -269,9 +269,9 @@ \subsubsection{Тестирование репликации} [slavedb] $ ps -ef | grep receiver postgres 6878 6872 1 10:31 ? 00:00:01 postgres: wal receiver process streaming 0/2000000 -\end{lstlisting} +\end{lstlisting}репликацию -Давайте проверим реприкацию и выполним на мастере: +Давайте проверим репликацию и выполним на мастере: \begin{lstlisting}[language=SQL,label=lst:streaming17,caption=Выполняем на мастере] $ psql test_db diff --git a/utils/pgadmin.tex b/utils/pgadmin.tex index 834b68cf..51083de7 100644 --- a/utils/pgadmin.tex +++ b/utils/pgadmin.tex @@ -2,7 +2,7 @@ \section{pgAdmin} \href{https://www.pgadmin.org/}{pgAdmin}~--- инструмент c графическим интерфейсом для управления PostgreSQL и производных от него баз данных. Он может быть запущен в качестве десктоп или веб-приложения. Написан на Python (с использованием Flask фреймворка) и JavaScript (с использованием jQuery и Bootstrap). -Cуществуют альтернативные програмные продукты для PostgreSQL (как платные, так и бесплатные). Вот примеры бесплатных альтернатив: +Существуют альтернативные программные продукты для PostgreSQL (как платные, так и бесплатные). Вот примеры бесплатных альтернатив: \begin{itemize} \item \href{http://dbeaver.jkiss.org/}{DBeaver};