Расширение pgpro_usage предоставляет статистику доступа к отношениям и вызовов функций в разрезе пользователей.
Если сервер выключен, собранная pgpro_usage статистика хранится в файле $PGDATA/pg_stat/pgpro_usage.stat. Чтобы сохранить статистику при переключении на резервный сервер, вам нужно вручную скопировать файл с предыдущего основного сервера или восстановить его из резервной копии.
pgpro_usage #Расширение pgpro_usage включено в состав Postgres Pro Enterprise как стандартное расширение. Чтобы задействовать pgpro_usage, выполните следующие действия:
Добавьте pgpro_usage в переменную shared_preload_libraries в файле postgresql.conf:
shared_preload_libraries = 'pgpro_usage'
Перезапустите сервер базы данных, чтобы изменения вступили в силу. Чтобы убедиться, что библиотека pgpro_usage установлена корректно, вы можете выполнить следующую команду:
SHOW shared_preload_libraries;
Создайте расширение pgpro_usage, выполнив следующий запрос:
CREATE EXTENSION pgpro_usage;
pgpro_usage #Чтобы корректно удалить расширение pgpro_usage, выполните следующие действия:
Удалите расширение pgpro_usage, выполнив следующий запрос:
DROP EXTENSION pgpro_usage;
Удалите pgpro_usage из переменной shared_preload_libraries в файле postgresql.conf.
Чтобы собирать статистику доступа отношений и вызовов функций в разрезе пользователей, pgpro_usage предоставляет SQL-интерфейс, состоящий из нескольких функций и представлений.
pg_stat_get_read_req_per_user(targetoid oid, roleoid oid) → BIGINT Возвращает число запросов пользователя/роли, указанной в roleoid, на чтение таблицы/индекса, указанного в targetoid.
pg_stat_get_insert_req_per_user(targetoid oid, roleoid oid) → BIGINT Возвращает число запросов пользователя/роли, указанной в roleoid, на вставку данных в таблицу, указанную в targetoid.
pg_stat_get_update_req_per_user(targetoid oid, roleoid oid) → BIGINT Возвращает число запросов пользователя/роли, указанной в roleoid, на обновление данных в таблице, указанной в targetoid.
pg_stat_get_delete_req_per_user(targetoid oid, roleoid oid) → BIGINT Возвращает число запросов пользователя/роли, указанной в roleoid, на удаление данных из таблицы, указанной в targetoid.
pg_stat_get_truncate_req_per_user(targetoid oid, roleoid oid) → BIGINT Возвращает число запросов пользователя/роли, указанной в roleoid, на опустошение таблицы, указанной в targetoid.
pg_stat_get_grants_given_per_user(targetoid oid, roleoid oid) → BIGINT Возвращает число команд GRANT и REVOKE, выполненных пользователем/ролью, указанной в roleoid, для таблицы, указанной в targetoid.
pg_stat_get_last_read_per_user(targetoid oid, roleoid oid) → timestamp with timezone Возвращает дату и время, когда пользователь/роль, указанная в roleoid, в последний раз выполнила SELECT для таблицы, указанной в targetoid.
pg_stat_get_last_insert_per_user(targetoid oid, roleoid oid) → timestamp with timezone Возвращает дату и время, когда пользователь/роль, указанная в roleoid, в последний раз выполнила INSERT для таблицы, указанной в targetoid.
pg_stat_get_last_update_per_user(targetoid oid, roleoid oid) → timestamp with timezone Возвращает дату и время, когда пользователь/роль, указанная в roleoid, в последний раз выполнила UPDATE для таблицы, указанной в targetoid.
pg_stat_get_last_delete_per_user(targetoid oid, roleoid oid) → timestamp with timezone Возвращает дату и время, когда пользователь/роль, указанная в roleoid, в последний раз выполнила DELETE для таблицы, указанной в targetoid.
pg_stat_get_last_truncate_per_user(targetoid oid, roleoid oid) → timestamp with timezone Возвращает дату и время, когда пользователь/роль, указанная в roleoid, в последний раз выполнила TRUNCATE для таблицы, указанной в targetoid.
pg_stat_get_func_calls_per_user(targetoid oid, roleoid oid) → BIGINT Возвращает число вызовов функции, указанной в targetoid, пользователем/ролью, указанной в roleoid.
pg_stat_get_func_grants_given_per_user(targetoid oid, roleoid oid) → BIGINT Возвращает число команд GRANT и REVOKE, выполненных пользователем/ролью, указанной в roleoid, для функции, указанной в targetoid.
pgpro_usage_reset(full_reset bool default false) → void Сбрасывает статистику pgpro_usage. Если для параметра full_reset задано значение true, сбрасывается вся статистика. Если для параметра full_reset задано значение false, сброс не затрагивает статистику последнего использования таблиц.
pgpro_usage_get_last_reset_time() → timestamp with time zone Время последнего сброса статистики pgpro_usage.
pg_stat_all_tables_per_user #Представление pg_stat_all_tables_per_user содержит по одной строке для каждой комбинации пользователя/роли и таблицы в текущей базе данных (включая TOAST-таблицы) и показывает статистику разных типов запросов пользователей к таблицам.
Таблица F.39. Столбцы pg_stat_all_tables_per_user
Столбец Тип Описание |
|---|
OID пользователя/роли |
Имя пользователя/роли |
OID таблицы |
Имя схемы, в которой находится эта таблица |
Имя этой таблицы |
Число запросов этого пользователя/роли на чтение этой таблицы |
Число запросов этого пользователя/роли на вставку данных в эту таблицу |
Число запросов от пользователя/роли на обновление данных в этой таблице |
Число запросов этого пользователя/роли на удаление данных из этой таблицы |
Число запросов пользователя/роли на опустошение этой таблицы |
Число команд |
pg_stat_all_tables_last_usage #Представление pg_stat_all_tables_last_usage содержит одну строку для каждой комбинации пользователя/роли и таблицы в текущей базе данных (включая TOAST-таблицы) и показывает дату и время последнего выполнения пользователями операций с таблицами.
Таблица F.40. Столбцы pg_stat_all_tables_last_usage
Столбец Тип Описание |
|---|
OID пользователя/роли |
Имя пользователя/роли |
Имя пространства имён |
OID таблицы |
Имя этой таблицы |
Дата и время последнего чтения этой таблицы этим пользователем/ролью |
Дата и время последней вставки данных в эту таблицу этим пользователем/ролью |
Дата и время последнего обновления этой таблицы этим пользователем/ролью |
Дата и время последнего удаления данных из этой таблицы этим пользователем/ролью |
Дата и время последнего опустошения этой таблицы этим пользователем/ролью |
pg_stat_all_functions_per_user #Представление pg_stat_all_functions_per_user содержит по одной строке для каждой комбинации пользователя/роли и пользовательской функции/хранимой процедуры/системной функции в текущей базе данных и показывает статистику вызовов функций и выдачи прав пользователями.
Таблица F.41. Столбцы pg_stat_all_functions_per_user
Столбец Тип Описание |
|---|
OID пользователя/роли |
Имя пользователя/роли |
OID функции |
Имя схемы, в которой находится функция |
Имя этой функции |
Число вызовов этой функции этим пользователем/ролью |
Число команд |
pgpro_usage_stats_privileges_usage #Представление pgpro_usage_stats_privileges_usage содержит по одной строке для каждой комбинации роли, права и объекта (таблицы или функции), на который роли имеют права. Строки показывают, каким образом были выданы права и были ли они использованы.
Таблица F.42. Столбцы pgpro_usage_stats_privileges_usage
Столбец Тип Описание |
|---|
Имя пользователя |
Тип права: |
Имя схемы, в которой находится объект (таблица или функция) |
Имя этого объекта (таблицы или функции) |
Имя роли, членство в которой позволило этой роли получить это право |
Имя роли, членство в которой позволило этой роли получить это право, или "public", если это право было выдано всем ролям с помощью |
Тип объекта: |
Было ли использовано это право |
pgpro_usage.max (integer) Определяет максимальное число пар объект-пользователь, которое хранит статистика. Объектом может быть таблица, функция или процедура. Вы можете уменьшить это значение для экономии памяти или увеличить его при использовании больших баз данных. Если расширению pgpro_usage требуется превысить заданное значение при записи статистики, новая запись не создаётся и отображается предупреждение «WARNING: max number of pgpro_usage records exceeded» (ПРЕДУПРЕЖДЕНИЕ: превышено максимальное число записей pgpro_usage).
Значение по умолчанию — 10000.
Этот пример демонстрирует использование расширения pgpro_usage.
Сначала создадим расширение:
postgres=# create extension pgpro_usage; CREATE EXTENSION
Теперь просмотрим статистику использования. Для этого создадим пользователя, таблицу и процедуру, после чего выдадим пользователю доступ к таблице:
postgres=# CREATE USER u1; CREATE ROLE postgres=# CREATE TABLE t1(val int); CREATE TABLE postgres=# GRANT all on t1 to u1; GRANT postgres=# CREATE PROCEDURE p1() AS $$ BEGIN RAISE NOTICE 'Here we are'; END; $$ LANGUAGE plpgsql; CREATE PROCEDURE
Выведем статистику использования всех таблиц:
postgres=# SELECT * FROM pg_stat_all_tables_per_user;
userid | username | relid | nspname | relname | n_reads | n_inserts | n_updates | n_deletes | n_truncates | n_grants_given
--------+----------+-------+---------+---------+---------+-----------+-----------+-----------+-------------+----------------
10 | postgres | 16445 | public | t1 | 0 | 0 | 0 | 0 | 0 | 1
(1 row)Сделаем то же самое для всех функций:
postgres=# SELECT * FROM pg_stat_all_functions_per_user;
userid | username | funcid | nspname | funcname | calls | grants_given
--------+----------+--------+---------+----------------------------------------+-------+--------------
10 | postgres | 16385 | public | pgpro_usage_reset | 0 | 1
10 | postgres | 16386 | public | pgpro_usage | 0 | 1
10 | postgres | 16387 | public | pgpro_usage_full | 0 | 1
10 | postgres | 16397 | public | pg_stat_get_func_calls_per_user | 2 | 0
10 | postgres | 16398 | public | pg_stat_get_func_grants_given_per_user | 1 | 0
10 | postgres | 16399 | public | pg_stat_get_read_req_per_user | 1 | 0
10 | postgres | 16400 | public | pg_stat_get_insert_req_per_user | 1 | 0
10 | postgres | 16401 | public | pg_stat_get_update_req_per_user | 1 | 0
10 | postgres | 16402 | public | pg_stat_get_delete_req_per_user | 1 | 0
10 | postgres | 16403 | public | pg_stat_get_truncate_req_per_user | 1 | 0
10 | postgres | 16404 | public | pg_stat_get_grants_given_per_user | 1 | 0
(11 rows) Приведённый выше вывод содержит только действия суперпользователя, который выдал доступ к таблице и несколько раз вызвал функции расширения при отправке запросов к приведённым выше представлениям. Столбец grants_given ненулевой в трёх строках. Они соответствуют отзыву прав у public при создании расширения. Созданный пользователь не включён в статистику, так как он не выполнял никаких действий.
Восполним этот пробел и подключимся к базе данных как пользователь u1.
postgres=# \c - u1 You are now connected to database "postgres" as user "u1". postgres=> insert into t1(val) values (1); INSERT 0 1 postgres=> insert into t1(val) values (2); INSERT 0 1 postgres=> select * from t1; val ----- 1 2 (2 rows) postgres=> call p1(); NOTICE: Here we are CALL
Мы выполнили две вставки в таблицу, отправили к ней один запрос и один раз вызвали процедуру. Переключимся обратно на суперпользователя и снова просмотрим статистику:
postgres=> \c - postgres
You are now connected to database "postgres" as user "postgres".
postgres=# SELECT * FROM pg_stat_all_tables_per_user;
userid | username | relid | nspname | relname | n_reads | n_inserts | n_updates | n_deletes | n_truncates | n_grants_given
--------+----------+-------+---------+---------+---------+-----------+-----------+-----------+-------------+----------------
16444 | u1 | 16445 | public | t1 | 1 | 2 | 0 | 0 | 0 | 0
10 | postgres | 16445 | public | t1 | 0 | 0 | 0 | 0 | 0 | 1
(2 rows)
postgres=# SELECT * FROM pg_stat_all_functions_per_user;
userid | username | funcid | nspname | funcname | calls | grants_given
--------+----------+--------+---------+----------------------------------------+-------+--------------
10 | postgres | 16385 | public | pgpro_usage_reset | 0 | 1
10 | postgres | 16386 | public | pgpro_usage | 0 | 1
10 | postgres | 16387 | public | pgpro_usage_full | 0 | 1
10 | postgres | 16397 | public | pg_stat_get_func_calls_per_user | 4 | 0
10 | postgres | 16398 | public | pg_stat_get_func_grants_given_per_user | 2 | 0
10 | postgres | 16399 | public | pg_stat_get_read_req_per_user | 2 | 0
10 | postgres | 16400 | public | pg_stat_get_insert_req_per_user | 2 | 0
10 | postgres | 16401 | public | pg_stat_get_update_req_per_user | 2 | 0
10 | postgres | 16402 | public | pg_stat_get_delete_req_per_user | 2 | 0
10 | postgres | 16403 | public | pg_stat_get_truncate_req_per_user | 2 | 0
10 | postgres | 16404 | public | pg_stat_get_grants_given_per_user | 2 | 0
16444 | u1 | 16448 | public | p1 | 1 | 0
(12 rows) Обе таблицы теперь содержат строки, соответствующие операциям пользователя u1: две вставки и одно чтение таблицы, а также одно выполнение процедуры.
Теперь просмотрим статистику последнего использования. Мы сможем увидеть временные метки, показывающие, когда пользователь выполнил вставку и чтение.
postgres=# select * from pg_stat_all_tables_last_usage; userid | username | nspname | relid | relname | last_read | last_insert | last_update | last_delete | last_truncate --------+----------+---------+-------+---------+-------------------------------+------------------------------+-------------+-------------+--------------- 16444 | u1 | public | 16445 | t1 | 2024-11-30 01:06:24.578642+03 | 2024-11-30 01:06:17.03442+03 | | | (1 row)
Дополним статистику чтением от суперпользователя:
postgres=# select * from t1;
val
-----
1
2
(2 rows)
postgres=# select * from pg_stat_all_tables_last_usage;
userid | username | nspname | relid | relname | last_read | last_insert | last_update | last_delete | last_truncate
--------+----------+---------+-------+---------+-------------------------------+------------------------------+-------------+-------------+---------------
10 | postgres | public | 16445 | t1 | 2024-11-30 01:09:29.994188+03 | | | |
16444 | u1 | public | 16445 | t1 | 2024-11-30 01:06:24.578642+03 | 2024-11-30 01:06:17.03442+03 | | |
(2 rows) Убедимся, что временная метка last_read обновилась:
postgres=# select * from t1;
val
-----
1
2
(2 rows)
postgres=# select * from pg_stat_all_tables_last_usage;
userid | username | nspname | relid | relname | last_read | last_insert | last_update | last_delete | last_truncate
--------+----------+---------+-------+---------+-------------------------------+------------------------------+-------------+-------------+---------------
10 | postgres | public | 16445 | t1 | 2024-11-30 01:10:28.122489+03 | | | |
16444 | u1 | public | 16445 | t1 | 2024-11-30 01:06:24.578642+03 | 2024-11-30 01:06:17.03442+03 | | |
(2 rows)Просмотрим статистику неиспользуемых прав. Объектов, пользователей и прав может существовать много, поэтому поместим всё, что относится к этому примеру, в отдельную схему. Так будет проще фильтровать результаты. Создаём схему и таблицу внутри неё, выдаём доступ к таблице определённой групповой роли и выдаём членство в этой групповой роли отдельному пользователю:
postgres=# create schema shops; CREATE SCHEMA postgres=# create table shops.buildings(); CREATE TABLE postgres=# create role manager; CREATE ROLE postgres=# grant all on schema shops to manager; GRANT postgres=# grant all on shops.buildings to manager; GRANT postgres=# create user vasya; CREATE ROLE postgres=# grant manager to vasya; GRANT ROLE
Подключимся к базе данных от имени этого пользователя и выполним запрос к таблице:
postgres=# \c - vasya You are now connected to database "postgres" as user "vasya". postgres=> select * from shops.buildings; -- (0 rows)
Теперь переключимся на суперпользователя и просмотрим статистику прав:
postgres=> \c - postgres You are now connected to database "postgres" as user "postgres". postgres=# select * from pgpro_usage_stats_privileges_usage where usename='vasya' and nspname='shops'; usename | access | nspname | targetname | provider | grantee | kind | used ---------+----------+---------+------------+----------+---------+----------+------ vasya | INSERT | shops | buildings | manager | manager | RELATION | f vasya | SELECT | shops | buildings | manager | manager | RELATION | t vasya | UPDATE | shops | buildings | manager | manager | RELATION | f vasya | DELETE | shops | buildings | manager | manager | RELATION | f vasya | TRUNCATE | shops | buildings | manager | manager | RELATION | f (5 rows)
Статистика показывает, что пользователь vasya имеет полный доступ к таблице shops.buildings и все эти права он получил не напрямую, а как член групповой роли manager. Также видно, что из всех прав пользователь vasya использовал только SELECT. Обратите внимание, что статистика прав не показывает права суперпользователя, так как суперпользователь имеет полный доступ.