Skip to content

Схемы в PostgreSQL. Изучаем PostgreSQL вместе с Grant Fritchey

Пересказ статьи Grant Fritchey. PostgreSQL Schema. Learning PostgreSQL with Grant


Важным аспектом при построении и обслуживании базы данных является организация объектов в вашей базе данных. У вас могут быть таблицы, которые обслуживают различные направления, например, схема для операций с хранилищами данных и схема для продаж. Некоторым логинам может потребоваться доступ к определенным таблицам, но не к остальным. Вы можете захотеть изолировать одно множество объектов в базе данных от других множеств объектов. Все это, и многое другое, может быть выполнено при помощи схем в базе данных, и PostgreSQL поддерживает использование схемы именно для этих типов функциональности.

В тестовой базе данных, которую я использую для примеров к этой серии статей, была создана пара схем с таблицами в каждой из них. Вы можете посмотреть на эту базу данных в скрипте CreateDatabase.sql. Остальной код для этой статьи находится в папке 08_Schema.

Обслуживание схемы


Схема используется в первую очередь как механизм организации вашей базы данных. Далее вы можете перейти к использованию схемы для проектирования безопасности, управления доступом и тем, что пользователи могут видеть и делать в вашей базе данных. При создании пустой базы данных она будет включать схему по умолчанию public.

Когда вы создаете объект типа таблицы, он автоматически приписывается схеме по умолчанию, если не задано обратное. По умолчанию все логины в базе данных имеют доступ к схеме public (PostgreSQL 15 изменил это поведение по умолчанию, поэтому теперь пользователи не имеют прав на создание объектов в схеме public). Помимо этого поведения по умолчанию, схема public является просто одной из схем в базе данных, и большинство функций и правил, которые будут далее обсуждаться, применимы к этой схеме.

Для начала создадим свои собственные схемы. Синтаксис очень простой:

CREATE SCHEMA mytestschema;

Этот оператор создает схему с именем mytestschema. Для создания таблицы в этой схеме вы просто используете имя таблицы из двух частей (имя_схемы.имя_таблицы) в операторе CREATE TABLE, например, так:

create table mytestschema.testtable
(id int,
somevalue varchar(50));

Так же и при любых запросах:

select id from mytestschema.testtable;

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

create schema secondschema:

create table secondschema.testtable
(insertdate date,
someothervalue varchar(20));

Это совершенно допустимо. Если бы я написал то, что я считаю плохим кодом, например:

select * from testtable;

то, вероятно, получил бы следующую ошибку:

ERROR: relation "testtable" does not exist
(отношение "testtable" не существует)
LINE 2: select * from testtable;


Сначала кажется, что ошибка возникает потому, что PostgreSQL не может решить, из какой из двух таблиц брать данные. Скорее, потому, что логины имеют схему по умолчанию. Когда я выполняю запрос, подобный последнему, без указания схемы, где находится таблица, PostgreSQL смотрит путь по умолчанию. Если таблицы там нет, значит ее не существует. Это справедливо, хотя у меня есть две таблицы с этим именем. PostgreSQL не проверяет другие схемы "на всякий случай".

Ниже в этой статье я расскажу, как управлять схемами по умолчанию.

Если схема пустая, вы можете ее удалить:

drop table if exists secondschema.testtable;
drop schema if exists secondschema;

Если я сначала не удалю таблицу, возникнет ошибка:

SQL Error [2BP01]: ERROR: cannot drop schema mytestschema because other objects depend on it
(нельзя удалить схему mytestschema, поскольку от нее зависят другие объекты)
Detail: table mytestschema.testtable depends on schema mytestschema
(таблица mytestschema.testtable зависит от схемы mytestschema)
Hint: Use DROP ... CASCADE to drop the dependent objects too.
(используйте DROP ... CASCADE для удаления также и зависимых объектов)


В сообщении об ошибке дается совет, как исправить ситуацию. Я мог бы переписать запрос следующим образом:

drop schema if exists mytestschema cascade;

Плюс, что при этом будут удалены все таблицы, представления и т.д., присутствующие в данной схеме. Но есть и минус в том, что будут удалены все таблицы, представления и прочее без всяких предупреждений.

В каждой базе данных создается схема по умолчанию с именем public. Однако это только по умолчанию и, как в большинстве настроек по умолчанию, ее можно изменить. Фактически вы даже можете удалить схему public, если захотите. Я начал этот раздел с объяснения, как создать свою собственную схему, которой вы непосредственно управляете, в противоположность принимаемой по умолчанию.

Управление путями поиска по умолчанию


Помимо помощи в организации объектов вашей базы данных, схема помогает контролировать доступ к этим объектам. Я еще не углублялся в тему безопасности в этой серии и, вероятно, до нее еще далеко. Однако я немного расскажу о том, как схема помогает управлять безопасностью базы данных. (Мой коллега Ryan Booz недавно опубликовал статью на эту тему ).

В этом разделе я хочу более детально обсудить некоторые способы управления схемой по умолчанию.

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

На самом деле существует определенный список поиска для схемы, который вы можете увидеть, используя такой запрос:

show search_path;

Если вы ничего не меняли на сервере, то результаты по умолчанию будут такими:

"$user",public

Каждый пользователь имеет собственную схему, как в SQL Server. Это и есть схема $user, которую вы видите выше. Однако, если вы не указали схему, по умолчанию будет принята первая в списке поиска, public в данном случае. Мы можем добавить схему в список поиска для текущего подключения:

SET search_path TO radio,public;

Это не только добавит схему radio в search_path, но и изменит порядок в пути поиска, поэтому схема radio ищется до схемы public. Если вы выполните отключение, а потом подключитесь вновь, вы должны будете переустановить путь с помощью команды SET.

Если вы хотите сделать изменения пути принимаемыми по умолчанию, то можете использовать ALTER ROLE, чтобы установить для любой роли специфический путь поиска. Например:

ALTER ROLE scaryDba SET search_path = 'radio,public,$user';

Если вы хотите установить значение по умолчанию для сервера/кластера/базы данных, то можете изменить search_path в файле postgressql.cnf или использовать команду:

ALTER ROLE ALL SET search_path = '$user';

Это не будет иметь приоритета над индивидуальными установками путей, но сделает для каждого логина, который не имеет приоритетного пути поиска, необходимость указывать имя схемы при ссылках на любой объект. (Что, как уже отмечалось, является лучшей практикой.)

Владение и основные привилегии


Когда вы создаете схему, то можете определить владельца схемы, отличного от логина, который выполняет эту команду:

CREATE SCHEMA secureschema AUTHORIZATION radio_admin;

Схема, которую я еще не создал ранее, secureschema, будет создана с владельцем, являющимся ролью логина radio_admin (тоже еще не определенной, поскольку я еще не разбирался с безопасностью). Это будет гарантировать, что только логин radio_admin и, конечно, любая учетная запись, определенная как суперпользователь, смогут работать в этой схеме.

Вы можете также управлять поведением по схеме. Например, поскольку я установил независимую схему в этой базе данных и намереваюсь использовать ее в этой манере, я могу запретить доступ для всех логинов на создание объектов в схеме public (это необходимо только в PostgreSQL 14 и ранее, в 15 разрешение на создание не предоставляется по умолчанию):

REVOKE CREATE ON SCHEMA public FROM PUBLIC;

Здесь используется слово “public” в двух разных значениях. В первом, ‘public’, мы ссылаемся на схему с этим именем. Во втором, ‘PUBLIC’, мы говорим о роли, которая содержит всех пользователей в базе данных. Этот механизм призван гарантировать, что ничего случайно не будет помещено в схему public. Я бы сказал, что полезно следовать этой практике, если вы собираетесь использовать другие схемы, особенно, если вы используете их для обеспечения безопасности вашей базы данных.

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

Если вы не изолируете хранилище и доступ между схемами, то изначально не имеет большого смысла использовать какие-либо схемы помимо public. Однако большинство приложений имеет разнообразные уровни доступа, которыми он хотели бы управлять, и схемы предоставляют им подходящую реализацию этого типа безопасности. Если безопасность и не является проблемой, использование имен схем вместо размещения всех объектов в схеме public может быть выгодным также с точки зрения документирования.

Заключение


Схемы представляют собой контейнеры, которые позволяют сегментировать объекты и обеспечивать безопасность на более низком уровне, чем уровень базы данных. Использование схем, отличных от public, имеет хорошие преимущества. В PostgreSQL имеется несколько методов установки схемы по умолчанию, если ваши пользователи не любят использовать двойные имена.

Если вы знакомы со схемами в SQL Server, базовая функциональность схемы примерно та же, что и там. Однако есть дополнительная функциональность, подобно возможности управлять изменением списка поиска, которой обладает PostgreSQL.

Ссылки по теме


  1. Безопасность SQL Server - модель безопасности с использованием определяемых пользователем ролей

  2. Типы данных в PostgreSQL: изучаем PostgreSQL с Grant Fritchey


Обратные ссылки

Нет обратных ссылок

Комментарии

Показывать комментарии Как список | Древовидной структурой

Нет комментариев.

Автор не разрешил комментировать эту запись

Добавить комментарий

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Добавленные комментарии должны будут пройти модерацию прежде, чем будут показаны.