Check long running transactions
SELECT
FORMAT('SELECTR pg_terminate_backend(%s)', pid) AS "run to kill",
pid AS "process ID",
usename AS "username",
client_addr AS "source ip",
EXTRACT(EPOCH FROM (DATE_TRUNC('second', now() - pg_stat_activity.query_start))) AS "duration",
state as "state",
TRIM(LEADING E'\n' FROM query) AS "query" -- Adjusts query visualization in some softwares
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC;
show where a user has permissions
WITH
tables AS (
SELECT
catalog_name AS "catalog_name",
schema_name AS "schema_name",
tablename AS "table_name"
FROM information_schema.schemata
JOIN pg_tables ON schemata.schema_name = pg_tables.schemaname
),
roles AS (
SELECT 'role' AS kind, rolname AS name FROM pg_roles
UNION
SELECT 'user' AS kind, usename AS name FROM pg_user
),
permissions AS (
SELECT
tables.catalog_name AS "catalog_name",
tables.schema_name AS "schema_name",
tables.table_name AS "table_name",
roles.kind AS "role_kind",
roles.name AS "role_name",
HAS_TABLE_PRIVILEGE(roles.name, tables.schema_name || '.' || tables.table_name, 'select') AS "has_select",
HAS_TABLE_PRIVILEGE(roles.name, tables.schema_name || '.' || tables.table_name, 'insert') AS "has_insert",
HAS_TABLE_PRIVILEGE(roles.name, tables.schema_name || '.' || tables.table_name, 'update') AS "has_update",
HAS_TABLE_PRIVILEGE(roles.name, tables.schema_name || '.' || tables.table_name, 'delete') AS "has_delete",
HAS_TABLE_PRIVILEGE(roles.name, tables.schema_name || '.' || tables.table_name, 'references') AS "has_references"
FROM tables, roles
ORDER BY tables.schema_name ASC, tables.table_name ASC, roles.kind ASC, roles.name ASC
)
SELECT *
FROM permissions
WHERE
catalog_name IN ('my_app') AND
schema_name NOT IN ('pg_catalog') AND
table_name IN ('my_table', 'my_other_table') AND
role_name in ('app_reader') AND
has_select = false
show objects ownership
SELECT
pg_namespace.nspname AS "object_schema",
pg_class.relname AS "object_name",
pg_roles.rolname AS "owner",
case pg_class.relkind
when 'r' then 'TABLE'
when 'm' then 'MATERIALIZED_VIEW'
when 'i' then 'INDEX'
when 'S' then 'SEQUENCE'
when 'v' then 'VIEW'
when 'c' then 'TYPE'
else pg_class.relkind::text
end AS "object_type"
FROM pg_class
JOIN pg_roles ON pg_roles.oid = pg_class.relowner
JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE
pg_namespace.nspname NOT IN ('information_schema', 'pg_catalog')
AND pg_namespace.nspname NOT IN ('pg_toast')
AND pg_roles.rolname = current_user -- remove this if you want to see all objects
ORDER BY pg_namespace.nspname, pg_class.relname;
show table sizes
SELECT
pg_namespace.nspname AS "object_schema",
pg_class.relname AS "object_name",
CASE
WHEN pg_class.relkind = 'r' THEN 'ordinary table'
WHEN pg_class.relkind = 'i' THEN 'index'
WHEN pg_class.relkind = 'S' THEN 'sequence'
WHEN pg_class.relkind = 't' THEN 'TOAST table'
WHEN pg_class.relkind = 'v' THEN 'view'
WHEN pg_class.relkind = 'm' THEN 'materialized view'
WHEN pg_class.relkind = 'c' THEN 'composite type'
WHEN pg_class.relkind = 'f' THEN 'foreign table'
WHEN pg_class.relkind = 'p' THEN 'partitioned table'
WHEN pg_class.relkind = 'I' THEN 'partitioned index'
END AS "ojbect_kind",
pg_size_pretty(pg_total_relation_size(pg_class.oid)) AS "total_size"
FROM
pg_class
LEFT JOIN
pg_namespace ON (pg_namespace.oid = pg_class.relnamespace)
WHERE
pg_namespace.nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY
pg_total_relation_size(pg_class.oid) DESC;
WITH
table_sizes AS (
SELECT
pg_namespace.nspname AS "object_schema",
pg_class.relname AS "object_name",
CASE
WHEN pg_class.relkind = 'r' THEN 'ordinary table'
WHEN pg_class.relkind = 'i' THEN 'index'
WHEN pg_class.relkind = 'S' THEN 'sequence'
WHEN pg_class.relkind = 't' THEN 'TOAST table'
WHEN pg_class.relkind = 'v' THEN 'view'
WHEN pg_class.relkind = 'm' THEN 'materialized view'
WHEN pg_class.relkind = 'c' THEN 'composite type'
WHEN pg_class.relkind = 'f' THEN 'foreign table'
WHEN pg_class.relkind = 'p' THEN 'partitioned table'
WHEN pg_class.relkind = 'I' THEN 'partitioned index'
END AS "object_kind",
pg_size_pretty(pg_total_relation_size(pg_class.oid)) AS "total_size"
FROM
pg_class
LEFT JOIN
pg_namespace ON (pg_namespace.oid = pg_class.relnamespace)
WHERE
pg_namespace.nspname NOT IN ('pg_catalog', 'information_schema')
AND pg_class.relkind IN ('r', 'm', 'p')
ORDER BY
pg_total_relation_size(pg_class.oid) DESC
),
per_schema AS (
SELECT
pg_namespace.nspname AS "object_schema",
'N/A' AS "object_name",
'N/A' AS "ojbect_kind",
pg_size_pretty(SUM(pg_total_relation_size(pg_class.oid))) AS "total_size"
FROM
pg_class
LEFT JOIN
pg_namespace ON (pg_namespace.oid = pg_class.relnamespace)
WHERE
pg_namespace.nspname NOT IN ('pg_catalog', 'information_schema')
GROUP BY
pg_namespace.nspname
),
per_kind AS (
SELECT
'N/A' AS "object_schema",
'N/A' AS "object_name",
CASE
WHEN pg_class.relkind = 'r' THEN 'ordinary table'
WHEN pg_class.relkind = 'i' THEN 'index'
WHEN pg_class.relkind = 'S' THEN 'sequence'
WHEN pg_class.relkind = 't' THEN 'TOAST table'
WHEN pg_class.relkind = 'v' THEN 'view'
WHEN pg_class.relkind = 'm' THEN 'materialized view'
WHEN pg_class.relkind = 'c' THEN 'composite type'
WHEN pg_class.relkind = 'f' THEN 'foreign table'
WHEN pg_class.relkind = 'p' THEN 'partitioned table'
WHEN pg_class.relkind = 'I' THEN 'partitioned index'
END AS "ojbect_kind",
pg_size_pretty(SUM(pg_total_relation_size(pg_class.oid))) AS "total_size"
FROM
pg_class
LEFT JOIN
pg_namespace ON (pg_namespace.oid = pg_class.relnamespace)
WHERE
pg_namespace.nspname NOT IN ('pg_catalog', 'information_schema')
GROUP BY
pg_class.relkind
),
total AS (
SELECT
'N/A' AS "object_schema",
'N/A' AS "object_name",
'N/A' AS "ojbect_kind",
pg_size_pretty(SUM(pg_total_relation_size(pg_class.oid))) AS "total_size"
FROM
pg_class
LEFT JOIN
pg_namespace ON (pg_namespace.oid = pg_class.relnamespace)
WHERE
pg_namespace.nspname NOT IN ('pg_catalog', 'information_schema')
)
-- SELECT * FROM total
-- UNION ALL
-- SELECT * FROM per_schema
-- UNION ALL
SELECT * FROM table_sizes
-- UNION ALL SELECT * FROM per_kind;
create a read-only access
-- SET ROLE rolname; -- assume role "rolname", always use object owner for GRANTS
-- SELECT current_user; -- user name of current execution context
-- SELECT session_user; -- session user name
-- example schema
CREATE SCHEMA example_schema;
-- example tables
CREATE TABLE example_schema.example_table (key TEXT PRIMARY KEY, value TEXT);
CREATE TABLE example_schema.example_another_table (key TEXT PRIMARY KEY, value TEXT);
-- application role
CREATE ROLE example_app_ro NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION INHERIT;
ALTER DEFAULT PRIVILEGES IN SCHEMA example_schema GRANT SELECT ON TABLES TO example_app_ro;
GRANT USAGE ON SCHEMA example_schema TO example_app_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA example_schema TO example_app_ro;
-- example table read-only role
CREATE ROLE example_table_role_ro NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION INHERIT;
GRANT USAGE ON SCHEMA example_schema TO example_table_role_ro;
GRANT SELECT ON example_schema.example_table TO example_table_role_ro;
-- example another table read-only role
CREATE ROLE example_another_table_role_ro NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION INHERIT;
GRANT USAGE ON SCHEMA example_schema TO example_another_table_role_ro;
GRANT SELECT ON example_schema.example_another_table TO example_table_role_ro;
-- group role, granted example_table_role_ro and example_another_table_role_ro
CREATE ROLE example_group_ro NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION INHERIT;
GRANT example_table_role_ro TO example_group_ro;
GRANT example_another_table_role_ro TO example_group_ro;
-- user role, granted example_group_ro
CREATE ROLE example_user WITH NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION INHERIT LOGIN PASSWORD 'mysecretpassword' VALID UNTIL 'infinity';
GRANT example_group_ro TO example_user;
inspect default schema privileges
SELECT
pg_namespace.nspname AS "object_schema",
case pg_default_acl.defaclobjtype
when 'r' then 'TABLE'
when 'm' then 'MATERIALIZED_VIEW'
when 'i' then 'INDEX'
when 'S' then 'SEQUENCE'
when 'v' then 'VIEW'
when 'c' then 'TYPE'
else pg_default_acl.defaclobjtype::text
end AS "object_type",
pg_default_acl.defaclacl AS "default_acl"
FROM pg_default_acl
JOIN pg_namespace ON pg_default_acl.defaclnamespace = pg_namespace.oid;
change ownership
SET ROLE old_owner;
REASSIGN OWNED BY old_owner TO new_owner;
get user roles
SELECT
a.rolname AS "rolname",
b.rolname AS "rolname_memberof"
FROM pg_roles AS a
INNER JOIN pg_roles AS b ON pg_has_role(a.rolname, b.oid, 'member')
GROUP BY a.rolname;
run a postresql in docker
docker run --detach --name 'my-sgdb' \
--volume ${PWD}/pgdata:/var/lib/postgresql/data \
--publish 5432:5432 \
--env POSTGRES_USER=myuser \
--env POSTGRES_PASSWORD=mysecretpassword \
--env POSTGRES_DB=mydatabase \
postgres
docker exec -it 'my-sgdb' psql 'host=localhost user=myuser dbname=mydatabase'
docker run --rm -it postgres psql 'host=myhost user=myuser password=mysecretpassword dbname=mydatabase'