Поиск пользователя в PostgreSQL
Вопрос: В PostgreSQL есть запрос, который будет возвращать всех созданных пользователей?
Ответ: В PostgreSQL есть системная таблица с именем pg_user . Вы можете выполнить запрос к этой системной таблице, который возвращает всех пользователей, которые были созданы в PostgreSQL, а также информацию об этих пользователях.
Чтобы получить всех пользователей в PostgreSQL, вы можете выполнить следующий SQL-запрос:
SELECT usename
FROM pg_user;
Таблица pg_user содержит следующие столбцы:
| Столбец | Пояснение |
|---|---|
| usename | Имя пользователя (например: postgres, vaso и т.д.) |
| usesysid | Идентификатор пользователя (номер, назначенный PostgreSQL) |
| usecreatedb | Логическое значение, указывающее, может ли пользователь создавать базы данных (t или f) |
| usesuper | Логическое значение, указывающее, является ли пользователь суперпользователем (t или f) |
| usecatupd | Логическое значение, указывающее, может ли пользователь обновлять системные каталоги (t или f) |
| userepl | Логическое значение, указывающее, может ли пользователь инициировать репликацию (t или f) |
| passwd | Пароль для пользователя отображается как ******** |
| valuntil | Время истечения срока действия пароля |
| useconfig | Значения по умолчанию для переменных конфигурации во время выполнения |
Глава 19. Аутентификация клиентского приложения
При подключении к серверу базы данных, клиентское приложение указывает имя пользователя PostgreSQL , так же как и при обычном входе пользователя на компьютер с ОС Unix. При работе в среде SQL по имени пользователя определяется, какие у него есть права доступа к объектам базы данных (подробнее это описывается в Главе 20). Следовательно, важно указать на этом этапе, к каким базам пользователь имеет право подключиться.
Замечание: Как можно узнать из Глава 20, PostgreSQL управляет правами и привилегиями, используя термин «роли» . В этой главе под пользователем мы подразумеваем «роль с привилегией LOGIN» .
Аутентификация это процесс идентификации клиента сервером базы данных, а также определение того, может ли клиентское приложение (или пользователь запустивший приложение) подключиться с указанным именем пользователя.
PostgreSQL предлагает несколько различных методов аутентификации клиентов. Метод аутентификации конкретного клиентского соединения может основываться на адресе компьютера клиента, имени базы данных, имени пользователя.
Имена пользователей базы данных PostgreSQL не имеют прямой связи с пользователями операционной системы на которой запущен сервер. Если у всех пользователей базы данных заведена учётная запись в операционной системе сервера, то имеет смысл назначить им точно такие же имена для входа в PostgreSQL . Однако, сервер, принимающий удалённые подключения, может иметь большое количество пользователей базы данных, у которых нет учётной записи в ОС. В таких случаях не требуется соответствие между именами пользователей базы данных и именами пользователей операционной системы.
| Пред. | Начало | След. |
| Краткие аргументы | Уровень выше | Файл pg_hba.conf |
PostgreSQL. Как получить базы текущего пользователя?
Как получить БД, к которым пользователь имеет доступ? Или наоборот как узнать по БД, какие пользователи имеют к ней доступ?
Отслеживать
задан 4 янв 2017 в 18:23
while1pass while1pass
2,265 1 1 золотой знак 29 29 серебряных знаков 56 56 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Как получить БД, к которым пользователь имеет доступ? Или наоборот как узнать по БД, какие пользователи имеют к ней доступ?
Для PostgreSQL свойственна собственная методика раздачи прав доступа. Которую можно разделить на два «шага»:
- доступ непосредственно к серверу
- доступ к объектам сервера
Доступ к серверу
Доступ к серверу осуществляется, помимо конфигов, с помощью механизма «ролей». В узком смысле (читаем про роли) «роль» можно трактовать и как «пользователя». Каждая роль получает или не получает доступ ко всему кластеру баз данных на сервере. Информацию об этом можно получить следующим запросом:
SELECT rolname AS "User", -- название ролей CASE WHEN rolsuper OR rolcanlogin THEN 'Yes' ELSE 'No' END AS "Access" -- есть ли право для логина? FROM pg_roles;
--------------- User | Access ------+-------- pgsql | Yes User | Yes Testo | No ---------------
Доступ к объектам сервера
В данном случае будем выбирать объекты типа «база данных», и определять какая «роль» имеет к ним ACL с типом ‘CONNECT’ . Это можно реализовать следующим запросом:
WITH bases AS ( SELECT * FROM ( SELECT datname AS "db", (aclexplode(datacl)).grantor AS "grantor", (aclexplode(datacl)).grantee AS "grantee", (aclexplode(datacl)).privilege_type AS "type" FROM pg_database ) AS Query WHERE Query.type = 'CONNECT' ), roles AS ( SELECT * FROM pg_roles ) SELECT DISTINCT * FROM ( SELECT * FROM ( SELECT bases.db AS db, roles1.rolname AS user FROM bases LEFT JOIN roles AS roles1 ON bases.grantor = roles1.oid ) AS one UNION SELECT * FROM ( SELECT bases.db AS db, roles2.rolname AS user FROM bases LEFT JOIN roles AS roles2 ON bases.grantee = roles2.oid ) AS two ) AS res WHERE res.user NOTNULL
========================= db | user =================+======= database_clients | pgsql template0 | pgsql template1 | pgsql testo | User testo | pgsql testo_final | User =================+=======
15 полезных команд PostgreSQL
В сети много руководств по PostgreSQL, которые описывают основные команды. Но при погружении в работу возникают такие практические вопросы, для которых требуются продвинутые команды. Рассмотрим несколько таких команд на примерах, полезных как для разработчиков, так и для администраторов баз данных.
В сети много руководств по PostgreSQL, которые описывают основные команды. Но при погружении глубже в работу возникают такие практические вопросы, для которых требуются продвинутые команды.
Такие команды, или сниппеты, редко описаны в документации. Рассмотрим несколько на примерах, полезных как для разработчиков, так и для администраторов баз данных.
Получение информации о базе данных
Размер базы данных
Чтобы получить физический размер файлов (хранилища) базы данных, используем следующий запрос:
SELECT pg_database_size(current_database());
Результат будет представлен как число вида 41809016 .
current_database() — функция, которая возвращает имя текущей базы данных. Вместо неё можно ввести имя текстом:
SELECT pg_database_size('my_database');
Для того, чтобы получить информацию в человекочитаемом виде, используем функцию pg_size_pretty :
SELECT pg_size_pretty(pg_database_size(current_database()));
В результате получим информацию вида 40 Mb .
Перечень таблиц
Иногда требуется получить перечень таблиц базы данных. Для этого используем следующий запрос:
SELECT table_name FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','pg_catalog');
information_schema — стандартная схема базы данных, которая содержит коллекции представлений (views), таких как таблицы, поля и т.д. Представления таблиц содержат информацию обо всех таблицах баз данных.
Запрос, описанный ниже, выберет все таблицы из указанной схемы текущей базы данных:
SELECT table_name FROM information_schema.tables WHERE table_schema NOT IN ('information_schema', 'pg_catalog') AND table_schema IN('public', 'myschema');
В последнем условии IN можно указать имя определенной схемы.
Размер таблицы
По аналогии с получением размера базы данных размер данных таблицы можно вычислить с помощью соответствующей функции:
SELECT pg_relation_size('accounts');
Функция pg_relation_size возвращает объём, который занимает на диске указанный слой заданной таблицы или индекса.
Имя самой большой таблицы
Для того, чтобы вывести список таблиц текущей базы данных, отсортированный по размеру таблицы, выполним следующий запрос:
SELECT relname, relpages FROM pg_class ORDER BY relpages DESC;
Для того, чтобы вывести информацию о самой большой таблице, ограничим запрос с помощью LIMIT :
SELECT relname, relpages FROM pg_class ORDER BY relpages DESC LIMIT 1;
relname — имя таблицы, индекса, представления и т.п.
relpages — размер представления этой таблицы на диске в количествах страниц (по умолчанию одна страницы равна 8 Кб).
pg_class — системная таблица, которая содержит информацию о связях таблиц базы данных.
Перечень подключенных пользователей
Чтобы узнать имя, IP и используемый порт подключенных пользователей, выполним следующий запрос:
SELECT datname,usename,client_addr,client_port FROM pg_stat_activity;
Активность пользователя
Чтобы узнать активность соединения конкретного пользователя, используем следующий запрос:
SELECT datname FROM pg_stat_activity WHERE usename = 'devuser';
Работа с данными и полями таблиц
Удаление одинаковых строк
Если так получилось, что в таблице нет первичного ключа (primary key), то наверняка среди записей найдутся дубликаты. Если для такой таблицы, особенно большого размера, необходимо поставить ограничения (constraint) для проверки целостности, то удалим следующие элементы:
- дублирующиеся строки,
- ситуации, когда одна или более колонок дублируются (если эти колонки предполагается использовать в качестве первичного ключа).
Рассмотрим таблицу с данными покупателей, где задублирована целая строка (вторая по счёту).
Удалить все дубликаты поможет следующий запрос:
DELETE FROM customers WHERE ctid NOT IN (SELECT max(ctid) FROM customers GROUP BY customers.*);
Уникальное для каждой записи поле ctid по умолчанию скрыто, но оно есть в каждой таблице.
Последний запрос требователен к ресурсам, поэтому будьте аккуратны при его выполнении на рабочем проекте.
Теперь рассмотрим случай, когда повторяются значения полей.
Если допустимо удаление дубликатов без сохранения всех данных, выполним такой запрос:
DELETE FROM customers WHERE ctid NOT IN (SELECT max(ctid) FROM customers GROUP BY customer_id);
Если данные важны, то сначала нужно найти записи с дубликатами:
SELECT * FROM customers WHERE ctid NOT IN (SELECT max(ctid) FROM customers GROUP BY customer_id);
Перед удалением такие записи можно перенести во временную таблицу или заменить в них значение customer_id на другое.
Общая форма запроса на удаление описанных выше записей выглядит следующим образом:
DELETE FROM table_name WHERE ctid NOT IN (SELECT max(ctid) FROM table_name GROUP BY column1, [column 2,] );
Безопасное изменение типа поля
Может возникнуть вопрос о включении в этот список такой задачи. Ведь в PostgreSQL изменить тип поля очень просто с помощью команды ALTER . Давайте для примера снова рассмотрим таблицу с покупателями.
Для поля customer_id используется строковый тип данных varchar . Это ошибка, так как в этом поле предполагается хранить идентификаторы покупателей, которые имеют целочисленный формат integer . Использование varchar неоправданно. Попробуем исправить это недоразумение с помощью команды ALTER :
ALTER TABLE customers ALTER COLUMN customer_id TYPE integer;
Но в результате выполнения получим ошибку:
Это значит, что нельзя просто так взять и изменить тип поля при наличии данных в таблице. Так как использовался тип varchar , СУБД не может определить принадлежность значения к integer . Хотя данные соответствуют именно этому типу. Для того, чтобы уточнить этот момент, в сообщении об ошибке предлагается использовать выражение USING , чтобы корректно преобразовать наши данные в integer :
ALTER TABLE customers ALTER COLUMN customer_id TYPE integer USING (customer_id::integer);
В результате всё прошло без ошибок:
Обратите внимание, что при использовании USING кроме конкретного выражения возможно использование функций, других полей и операторов.
Например, преобразуем поле customer_id обратно в varchar , но с преобразованием формата данных:
ALTER TABLE customers ALTER COLUMN customer_id TYPE varchar USING (customer_id || '-' || first_name);
В результате таблица примет следующий вид:
Поиск «потерянных» значений
Будьте внимательны при использовании последовательностей (sequence) в качестве первичного ключа (primary key): при назначении некоторые элементы последовательности случайно пропускаются, в результате работы с таблицей некоторые записи удаляются. Такие значения можно использовать снова, но найти их в больших таблицах сложно.
Рассмотрим два варианта поиска.
Первый способ
Выполним следующий запрос, чтобы найти начало интервала с «потерянным» значением:
SELECT customer_id + 1 FROM customers mo WHERE NOT EXISTS ( SELECT NULL FROM customers mi WHERE mi.customer_id = mo.customer_id + 1 ) ORDER BY customer_id;
В результате получим значения: 5 , 9 и 11 .
Если нужно найти не только первое вхождение, а все пропущенные значения, используем следующий (ресурсоёмкий!) запрос:
WITH seq_max AS ( SELECT max(customer_id) FROM customers ), seq_min AS ( SELECT min(customer_id) FROM customers ) SELECT * FROM generate_series((SELECT min FROM seq_min),(SELECT max FROM seq_max)) EXCEPT SELECT customer_id FROM customers;
В результате видим следующий результат: 5 , 9 и 6 .
Второй способ
Получаем имя последовательности, связанной с customer_id :
SELECT pg_get_serial_sequence('customers', 'customer_id');
И находим все пропущенные идентификаторы:
WITH sequence_info AS ( SELECT start_value, last_value FROM "SchemaName"."SequenceName" ) SELECT generate_series ((sequence_info.start_value), (sequence_info.last_value)) FROM sequence_info EXCEPT SELECT customer_id FROM customers;
Подсчёт количества строк в таблице
Количество строк вычисляется стандартной функцией count , но её можно использовать с дополнительными условиями.
Общее количество строк в таблице:
SELECT count(*) FROM table;
Количество строк при условии, что указанное поле не содержит NULL :
SELECT count(col_name) FROM table;
Количество уникальных строк по указанному полю:
SELECT count(distinct col_name) FROM table;
Использование транзакций
Транзакция объединяет последовательность действий в одну операцию. Её особенность в том, что при ошибке в выполнении транзакции ни один из результатов действий не сохранится в базе данных.
Начнём транзакцию с помощью команды BEGIN .
Для того, чтобы откатить все операции, расположенные после BEGIN , используем команду ROLLBACK .
А чтобы применить — команду COMMIT .
Просмотр и завершение исполняемых запросов
Для того, чтобы получить информацию о запросах, выполним следующую команду:
SELECT pid, age(query_start, clock_timestamp()), usename, query FROM pg_stat_activity WHERE query != '' AND query NOT ILIKE '%pg_stat_activity%' ORDER BY query_start desc;
Для того, чтобы остановить конкретный запрос, выполним следующую команду, с указанием id процесса (pid):
SELECT pg_cancel_backend(procpid);
Для того, чтобы прекратить работу запроса, выполним:
SELECT pg_terminate_backend(procpid);
Работа с конфигурацией
Поиск и изменение расположения экземпляра кластера
Возможна ситуация, когда на одной операционной системе настроено несколько экземпляров PostgreSQL, которые «сидят» на различных портах. В этом случае поиск пути к физическому размещению каждого экземпляра — достаточно нервная задача. Для того, чтобы получить эту информацию, выполним следующий запрос для любой базы данных интересующего кластера:
SHOW data_directory;
Изменим расположение на другое с помощью команды:
SET data_directory to new_directory_path;
Но для того, чтобы изменения вступили в силу, требуется перезагрузка.
Получение перечня доступных типов данных
Получим перечень доступных типов данных с помощью команды:
SELECT typname, typlen from pg_type where typtype='b';
typname — имя типа данных.
typlen — размер типа данных.
Изменение настроек СУБД без перезагрузки
Настройки PostgreSQL находятся в специальных файлах вроде postgresql.conf и pg_hba.conf . После изменения этих файлов нужно, чтобы СУБД снова получила настройки. Для этого производится перезагрузка сервера баз данных. Понятно, что приходится это делать, но на продакшн-версии проекта, которым пользуются тысячи пользователей, это очень нежелательно. Поэтому в PostgreSQL есть функция, с помощью которой можно применить изменения без перезагрузки сервера:
SELECT pg_reload_conf();
Но, к сожалению, она применима не ко всем параметрам. В некоторых случаях для применения настроек перезагрузка обязательна.
На данный момент этот блок не поддерживается, но мы не забыли о нём! Наша команда уже занята его разработкой, он будет доступен в ближайшее время.
Мы рассмотрели команды, которые помогут упростить работу разработчикам и администраторам баз данных, использующим PostgreSQL. Но это далеко не все возможные приёмы. Если вы сталкивались с интересными задачами, напишите о них в комментариях. Поделимся полезным опытом!

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