
【PostgreSQL】superuser_reserved_connections による一般ユーザーとスーパーユーザーの接続数上限の違いを検証してみた
PostgreSQL には superuser_reserved_connections というパラメータがあり、
スーパーユーザーのために一定数の接続スロットが予約されています。
今回は、一般ユーザーと superuser で実際に接続を埋めていき、
max_connections - superuser_reserved_connections の計算通りに
一般ユーザーの接続が制限されるのか、実際に確認してみました。
具体的には以下の内容を検証してみました。
- 一般ユーザー(test_user)で接続を埋めていき、想定通りの数で制限されるか確認
- 制限に達した後、superuser(postgres)の場合は、接続ができるか確認
max_connections (integer)
データベースサーバに同時接続する最大数を決定します。
...
superuser_reserved_connections (integer)
PostgreSQLのスーパーユーザによる接続のために予約されている接続「スロット」の数を決定します。...
(前提準備) PostgreSQL インストール
検証のための実行環境は EC2(AL2023)にインストールした PostgreSQL を使用しました。
EC2 に PostgreSQL をインストールする手順としては下記をご参照ください。
PostgreSQL 17.10 を利用し、検証していきます。
[ec2-user@ip-xx-xx-xx-xx ~]$ sudo -u postgres psql
psql (17.10)
Type "help" for help.
postgres=# SELECT version();
version
---------------------------------------------------------------------------------------------------------------
PostgreSQL 17.10 on x86_64-amazon-linux-gnu, compiled by gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-5), 64-bit
(1 row)
現在の接続ユーザーが superuser か確認
基本的に PostgreSQL をインストールした時点で、デフォルトユーザーとして postgres が作られますがそのユーザーが superuser かどうか念の為確認します。
以下の通り、現在は ユーザー postgres で接続しています。
postgres=# SELECT current_user, session_user;
current_user | session_user
--------------+--------------
postgres | postgres
(1 row)
ロール一覧を確認。ロール(ユーザー) postgres には Superuser 権限が付与されています。
postgres=# \du
List of roles
Role name | Attributes
-----------+------------------------------------------------------------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS
\du[S+] [ pattern ]
データベースロールを一覧表示します。 (「ユーザ」と「グループ」という概念は「ロール」に統合されましたので、このコマンドは\dgと同じものになりました。)
上記の確認方法の他、pg_roles ビューを確認する方法もあります。
-- rolsuper が t(true)であれば superuser
postgres=# SELECT rolname, rolsuper FROM pg_roles WHERE rolname = current_user;
rolname | rolsuper
----------+----------
postgres | t
(1 row)
52.20. pg_roles
pg_rolesビューはデータベースのロールに関する情報を提供します。
...
rolsuperbool
ロールはスーパーユーザの権限を持っている
以上より、ユーザー postgres はスーパーユーザー権限を持っていることがわかります。
後ほど作成する一般ユーザー(test_user)でも同様のコマンドを実行し、比較していきます。
max_connections を小さくする
検証をしやすくするため max_connections の値を小さくします。
まずは、現在の max_connections および superuser_reserved_connections の値を確認します。
postgres=# SHOW max_connections;
max_connections
-----------------
100
(1 row)
postgres=# SHOW superuser_reserved_connections;
superuser_reserved_connections
--------------------------------
3
(1 row)
以下記事の「max_connections の変更」の手順を参考に max_connections の値を 5 に変更します。
以下のようになっていれば OK です。(superuser_reserved_connections はそのままです。)
postgres=# SHOW max_connections;
max_connections
-----------------
5
(1 row)
postgres=# SHOW superuser_reserved_connections;
superuser_reserved_connections
--------------------------------
3
(1 row)
検証用の一般ユーザーを作る
検証用に test_user ロール(ユーザー)を作成します。
-- ロール作成
postgres=# CREATE ROLE test_user WITH LOGIN PASSWORD 'testpass123';
CREATE ROLE
作成した test_user の権限も確認しておきます。
下記の通り、rolsuper が f のため、本ユーザーは superuser 権限を持たない、ごく一般的なロールであることがわかります。
postgres=# SELECT rolname, rolsuper FROM pg_roles WHERE rolname = 'test_user';
rolname | rolsuper
-----------+----------
test_user | f
(1 row)
postgres=# \du
List of roles
Role name | Attributes
-----------+------------------------------------------------------------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS
test_user |
一般ユーザーから接続できるよう pg_hba.conf を修正
作成済みの test_user で PostgreSQL サーバーへ接続自体ができるか確認します。
現在、接続を試行すると下記の通りエラーとなります。
$ psql -U test_user -d postgres
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "test_user"
上記エラーの理由は、local(Unixソケット)接続では peer 認証方式が使われているためです。(pg_hba.conf にて設定されるパラメータ)
peer 設定では OS ユーザー名と PostgreSQL のロール名が一致するかを認証します。
今回は EC2 環境を用いているので EC2 の OS ユーザー ec2-user から test_user としてログインしようとしたため、認証エラーとなりました。
peer
クライアントのオペレーティングシステムにおけるユーザ名をオペレーティングシステムから取得し、ユーザ名が要求されたデータベースユーザ名と一致するか検査します。 これはローカル接続の時にのみ使用可能です。
そのため、pg_hba.conf を編集し、認証方式をパスワード認証が必要な scram-sha-256 に変更します。
scram-sha-256
ユーザのパスワードを検証するためにSCRAM-SHA-256認証を実行します。
scram-sha-256 方式では、ログインの際にパスワードが必須となるため、デフォルトユーザー postgres のパスワードも予め設定しておきましょう。
-- postgres ユーザーでログインし、
-- 本ユーザーの接続用に任意のパスワードを設定しておく
postgres=# ALTER ROLE postgres WITH PASSWORD 'your_strong_password';
ALTER ROLE
上記にてパスワード変更ができたら、pg_hba.conf を編集します。
vim エディタで設定ファイルを開きます。
$ sudo vi /var/lib/pgsql/data/pg_hba.conf
下記のように scram-sha-256 を使用するよう変更します。
# 変更前
local all all peer
# 変更後
local all all scram-sha-256
変更を反映させるため PostgreSQL をリロードします。
$ sudo systemctl reload postgresql
再度一般ユーザー test_user で試してみると、パスワードが求められ、
ユーザー作成時に指定したパスワードを入力すると、接続ができました。
$ psql -U test_user -d postgres
Password for user test_user:
psql (17.10)
Type "help" for help.
postgres=>
もちろん、デフォルトユーザー postgres で試しても、
パスワード入力が求められ、接続ができました。
$ sudo -u postgres psql
Password for user postgres:
psql (17.10)
Type "help" for help.
postgres=#
一般ユーザーで接続を埋める
※本検証を始める際は superuser 権限を持つ postgres ユーザーからの接続は全て切断しておいてください。以下のように test_user からの接続のみになっていれば OK です。
postgres=> SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity WHERE backend_type = 'client backend';
pid | usename | state | backend_type | query_start
--------+-----------+--------+----------------+-------------------------------
104731 | test_user | active | client backend | 2026-08-15 11:15:56.611448+00
(1 row)
現在は max_connections=5, superuser_reserved_connections=3 です。
そして現在 PostgreSQL に接続しているのは本クエリを実行している自分(test_user)の 1 接続のみです。
postgres=# SHOW max_connections;
max_connections
-----------------
5
(1 row)
postgres=# SHOW superuser_reserved_connections;
superuser_reserved_connections
--------------------------------
3
(1 row)
-- 現在接続しているクライアントを確認
postgres=> SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity WHERE backend_type = 'client backend';
pid | usename | state | backend_type | query_start
--------+-----------+--------+----------------+-------------------------------
104731 | test_user | active | client backend | 2026-08-15 11:15:56.611448+00
(1 row)
公式ドキュメントを確認すると、以下の通り、最大接続数は max_connections であり、その内の superuser_reserved_connections がスーパーユーザーのために予約された接続数と読み取れます。
max_connections (integer)
データベースサーバに同時接続する最大数を決定します。
...
superuser_reserved_connections (integer)
PostgreSQLのスーパーユーザによる接続のために予約されている接続「スロット」の数を決定します。
すなわち、一般ユーザーである test_user から接続できる数は下記の計算式になるはずです。
一般ユーザーの枠 = max_connections - superuser_reserved_connections
今回の場合は 5 - 3 = 2 です。本当にそうなるか確認してみましょう。
ターミナル B を開き、test_user で接続を試行します。
$ PGPASSWORD='testpass123' psql -U test_user -d postgres -c "SELECT pg_sleep(300);" &
[1] 104896
ターミナル A から確認すると先ほどと比較し、接続が増えていることがわかります。
postgres=> SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity WHERE backend_type = 'client backend';
pid | usename | state | backend_type | query_start
--------+-----------+--------+----------------+-------------------------------
104731 | test_user | active | client backend | 2026-08-15 11:21:46.584027+00
104897 | test_user | active | client backend | 2026-08-15 11:20:38.093783+00
(2 rows)
それではターミナル B から同じ test_user でもう1接続追加してみます。(3接続目)
その結果、今度は失敗しました。
$ PGPASSWORD='testpass123' psql -U test_user -d postgres -c "SELECT pg_sleep(300);" &
[2] 104956
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: remaining connection slots are reserved for roles with the SUPERUSER attribute
もちろん、ターミナル A の pg_stat_activity の内容も変化はありません。
postgres=> SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity WHERE backend_type = 'client backend';
pid | usename | state | backend_type | query_start
--------+-----------+--------+----------------+-------------------------------
104731 | test_user | active | client backend | 2026-08-15 11:23:15.512422+00
104897 | test_user | active | client backend | 2026-08-15 11:20:38.093783+00
(2 rows)
では続いて ターミナル B から superuser 権限を持つ postgres で接続してみましょう。
下記の通り無事入れました。
$ sudo -u postgres psql
Password for user postgres:
psql (17.10)
Type "help" for help.
postgres=#
一方で、ターミナル A から接続が増えたかどうか確認しますが、接続は増えていないように見えます。
postgres=> SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity WHERE backend_type = 'client backend';
pid | usename | state | backend_type | query_start
--------+-----------+--------+----------------+-------------------------------
104731 | test_user | active | client backend | 2026-08-15 11:25:37.473418+00
104897 | test_user | active | client backend | 2026-08-15 11:20:38.093783+00
(2 rows)
上記のように postgres の接続が見えないのは、WHERE 句条件を付けているためです。下記の通り外すと pid=105017 の postgres 接続が増えていることがわかります。
(一般ユーザー test_user で pg_stat_activity を見ると、自分以外のユーザーの backend_type や state が空欄になっていました。権限による表示制限があるようです)
postgres=> SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity;
pid | usename | state | backend_type | query_start
--------+-----------+--------+----------------+-------------------------------
105017 | postgres | | |
104731 | test_user | active | client backend | 2026-08-15 11:31:28.160154+00
105189 | test_user | active | client backend | 2026-08-15 11:30:42.105777+00
2729 | | | |
2730 | postgres | | |
2725 | | | |
2726 | | | |
2728 | | | |
(8 rows)
ちなみに superuser の postgres で接続したターミナル B から見ると、postgres の接続が増えていることがわかります。
postgres=# SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity WHERE backend_type = 'client backend';
pid | usename | state | backend_type | query_start
--------+-----------+--------+----------------+-------------------------------
104731 | test_user | idle | client backend | 2026-08-15 11:25:16.354961+00
104897 | test_user | active | client backend | 2026-08-15 11:20:38.093783+00
105017 | postgres | active | client backend | 2026-08-15 11:25:32.481231+00
(3 rows)
予想通り、max_connections=5, superuser_reserved_connections=3 の状態の場合、
一般ユーザーからの接続は superuser_reserved_connections を差し引いた 5 - 3 = 2 接続しかできませんが、superuser権限を持つユーザーであればちゃんと接続ができていることがわかりました。
終わりに
今回の検証で、以下のことが確認できました。
- サーバーへの接続数は
max_connectionsによって上限が定められている superuser_reserved_connectionsにより、予めスーパーユーザー用の接続が予約されている。- そのため、一般ユーザーが使える接続数は
max_connections - superuser_reserved_connectionsとなる
superuser_reserved_connections があることで、何らかの理由で一般ユーザーからの接続が急増してトラブルになった場合でも、スーパーユーザーで接続して調査することができます。
本パラメータのように、データベース技術は障害対応まで見据えた設計になっていることに気づき、勉強になりました。
本記事がどなたかのお役に立てば幸いです。
参考情報



