0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

# PostgreSQL 16から17へのバージョンアップ手順 ─ Amazon Linux 2023標準で試してみた

0
Posted at

1. はじめに

本記事は、私が書いたPostgreSQL16でpgbenchを使ってみたから続く、PostgreSQL16パフォーマンスチューニングシリーズの 17対応版 の一本目です。

シリーズ#1ではEC2(t3.micro)上に、Amazon Linux 2023の標準リポジトリpostgresql16-server をインストールしてpgbench環境を作りました。本記事はその環境を PostgreSQL17へバージョンアップする手順 を、dump/restore を実際に手を動かして確認します。

ただし、先に結論の一部を書いておきます。Amazon Linux 2023の標準リポジトリのままだと、16と17を共存させてpg_upgradeを素直に使うのは難しい です。本記事はその制約を隠さず、その上で「ではどうするか」を両方式について示します。

アップグレード前後でpgbenchのTPSがどう変わるかは、別記事で実測する予定です。本記事は 手順そのもの に集中します。

1.1 この記事でできるようになること

  • 標準リポジトリ環境での16から17バージョンアップ手順を理解する
  • なぜ標準リポジトリだとpg_upgradeが難しいのか、その理由を理解する
  • 確実な dump/restore 方式を最後まで実行できる
  • それでもpg_upgradeを使う場合の回避策と注意点を理解する
  • アップグレード後に必須となる作業(ANALYZE・拡張の入れ直し)を理解する
  • pg_repack のような contrib 外の拡張が移行時にどう問題になるかを理解する

1.2 検証環境(シリーズ#1と同じ)

項目 内容
OS Amazon Linux 2023
移行元 PostgreSQL 16(標準リポジトリ postgresql16-server
移行先 PostgreSQL 17(標準リポジトリ postgresql17-server
インスタンスタイプ t3.micro(2 vCPU、1GiB メモリ)EBS 30GB
データディレクトリ /var/lib/pgsql/data
サービス名 postgresql

シリーズ#1で sudo -u postgres pgbench -i -s 1 pgbench_test のようにフルパスなしで実行できているのは、標準リポジトリのバイナリがPATH上にあるためです。本記事もこの前提(フルパス指定なし)で書きます。


2. 【重要】なぜ標準リポジトリだと共存が難しいのか

PostgreSQLの公式が提供する PGDGリポジトリ では、バージョンごとに以下が分離されます。

  • バイナリ:/usr/pgsql-16/bin//usr/pgsql-17/bin/
  • データ:/var/lib/pgsql/16/data/var/lib/pgsql/17/data
  • サービス:postgresql-16postgresql-17

この分離があるからこそ、pg_upgrade は「旧バイナリ・旧データ」と「新バイナリ・新データ」を別々に指定でき、両者を同時に扱えます。

ところが Amazon Linux 2023の標準リポジトリpostgresql16 / postgresql17 パッケージは、設計思想が異なります。

項目 標準リポジトリの挙動
データディレクトリ どちらも /var/lib/pgsql/data を使う
サービス名 どちらも postgresql.service
クライアントコマンド psql 等が同じ名前でPATH上に置かれ衝突しうる

つまり標準リポジトリのまま postgresql16postgresql17 を同時にインストールすると、データディレクトリ・サービス・コマンドがすべて競合し、pg_upgradeが前提とする「新旧を別々に並べて指定する」構成が素直に作れません

これはPGDGリポジトリとの決定的な違いです。シリーズ#1が標準リポジトリを選んでいるため、本記事ではこの制約を踏まえてバージョンアップを実施します。

2.1 この制約を踏まえた現実的な選択肢

方式 標準リポジトリでの現実性 備考
dump / restore ◎ 素直にできる 16をアンインストール→17を入れる、の流れで完結
pg_upgrade △ 工夫が必要 17を非標準パスへ手動配置するなど標準運用から外れる

検証環境(t3.micro・pgbenchの小規模テーブル)であれば、dump/restoreが圧倒的に素直 です。本記事はdump/restoreを軸に据え、pg_upgradeは「やるならこうなる/なぜ大変か」を6章で解説します。


3. 事前準備(両方式 共通)

3.1 現状の確認

# 16が動いていることを確認
sudo systemctl status postgresql

# バージョン確認(シリーズ#1では 16.12 でした)
sudo -u postgres psql -c "SELECT version();"

導入済み拡張の棚卸し(重要)

移行で最もハマりやすいのが拡張です。リストア前に 何の拡張が入っているか を必ず控えておきます。

sudo -u postgres psql -d pgbench_test -Atc \
  "SELECT extname, extversion FROM pg_extension ORDER BY extname;"

このシリーズの環境では、以下の5つが導入されています。

拡張 区分 17での対応
pg_prewarm contrib postgresql17-contrib でOK
pg_repack contrib外 別パッケージ(pg_repack_17 等)が別途必要
pg_stat_statements contrib postgresql17-contrib でOK
pgstattuple contrib postgresql17-contrib でOK
plpgsql 標準同梱 何もしなくてOK

ポイントは contrib外で要注意なのは pg_repack ただ1つ という点です。pg_repackpostgresql17-contrib には含まれず、これを入れただけでは復元できません。リストア時に extension "pg_repack" is not available というエラーになります。後述で対処します。なお /usr/pgsql-16/ 配下にpg_repack関連ファイルが置かれていますが、これはpg_repackパッケージ固有の配置で、PostgreSQL本体(/usr/bin/postgres 等)とは無関係です。

3.2 バックアップ(必須)

バージョンアップ作業の前に、必ず全データの論理バックアップを取得します。dump/restore方式ではこのダンプ自体が移行データになります。

【実際にハマった落とし穴】/tmp はメモリの上にある
t3.micro + Amazon Linux 2023標準構成では、/tmptmpfs(メモリ上のファイルシステム) になっています。サイズはメモリに連動して数百MB程度(筆者環境では459MB)しかありません。

df -h /tmp        # → tmpfs、容量が数百MBしかない
mount | grep /tmp # → type tmpfs

ここで何も考えず pg_dumpall -f /tmp/dump_all.sql とすると、DBが少し大きいだけで No space left on device で即死します(筆者は約9GBのDBで459MB時点で失敗)。ルートFSに十分空きがあっても関係ありません。ダンプ先は必ずルートFS上の通常ディレクトリにし、さらに圧縮する のが鉄則です。

専用ディレクトリを作り、gzip で圧縮しながらダンプします。

# ルートFS上にバックアップ用ディレクトリを用意
sudo mkdir -p /var/backups/pg
sudo chown postgres:postgres /var/backups/pg

# 圧縮しながらダンプ(プレーンSQLは肥大しやすいので圧縮が実質必須)
sudo -u postgres bash -c "pg_dumpall | gzip > /var/backups/pg/dump_all_$(date +%Y%m%d).sql.gz"

# 取得できたか確認
ls -lh /var/backups/pg/

# 中身の先頭を確認(ロール定義などが入っているはず)
sudo -u postgres bash -c "gunzip -c /var/backups/pg/dump_all_*.sql.gz | head -n 20"

pg_dumpall はデータベース個別だけでなくロール(ユーザ)やテーブルスペースなどクラスタ全体を出力します。シリーズの pgbench_test データベースもこれに含まれます。なお筆者環境では 約9GBのDBが、gzip 圧縮で163MB まで小さくなりました(pgbenchのデータは規則的で圧縮が極めてよく効くため)。ただし圧縮なしのプレーンSQLだと数GB規模になり /tmp(tmpfs) では確実に失敗します。圧縮しても出力先には余裕を見て、df -h /var/backups/pg で事前確認しておくと安全です。

3.3 設定ファイルの退避

postgresql.confpg_hba.conf を別途控えておきます。17で初期化すると初期設定に戻るため、シリーズで変更したパラメータを後で見比べられるようにします。退避先は3.2と同じ永続ディレクトリにします(/tmp はtmpfsで再起動時に消えるため、設定バックアップの置き場所として不適切です)。

sudo cp /var/lib/pgsql/data/postgresql.conf /var/backups/pg/postgresql.conf.16.bak
sudo cp /var/lib/pgsql/data/pg_hba.conf     /var/backups/pg/pg_hba.conf.16.bak
ls -lh /var/backups/pg/

4. dump / restore 方式(本記事の推奨ルート)

標準リポジトリ環境で最も素直な手順です。流れは「ダンプ取得 → 16停止 → 16削除 → 17導入・初期化 → リストア」です。

4.1 ダンプ取得

3.2で取得済みであればそれを使います。まだなら、同じく圧縮ダンプを取得します(/tmp を使わないこと。理由は3.2参照)。

sudo -u postgres bash -c "pg_dumpall | gzip > /var/backups/pg/dump_all.sql.gz"
ls -lh /var/backups/pg/dump_all.sql.gz

4.2 PostgreSQL16の停止

sudo systemctl stop postgresql
sudo systemctl status postgresql   # stopped を確認

4.3 旧データの退避(保険)

削除前に、データディレクトリをアーカイブで丸ごと退避しておきます。万一のときの最後の砦です。退避先は3.2と同じくルートFS上にします(/tmp はtmpfsで容量不足になるため)。

sudo tar czf /var/backups/pg/pgsql_data_16_backup.tar.gz -C /var/lib/pgsql data
ls -lh /var/backups/pg/pgsql_data_16_backup.tar.gz

4.4 16の削除と17の導入

標準リポジトリでは同一パスを使うため、16を削除してから17を入れる のが素直です(共存させない割り切り)。

# 16系パッケージを削除(データディレクトリ /var/lib/pgsql/data は残る)
sudo dnf remove -y postgresql16-server postgresql16

# 念のため旧データディレクトリを退避してクリアする
sudo mv /var/lib/pgsql/data /var/lib/pgsql/data_16_old

# 17をインストール
sudo dnf install -y postgresql17-server postgresql17-contrib

dnf remove はデータディレクトリ(/var/lib/pgsql/data)を消しません。それでも4.3でアーカイブを取り、ここで data_16_old へ退避するのは、取り返しのつかない操作の前に保険を二重化する ためです。

contrib外の拡張(pg_repack)を17向けに導入する

3.1で確認した通り、この環境には pg_repack が入っています。pg_repackpostgresql17-contrib には含まれないため、17に対応する版を別途インストール しておかないと、4.6のリストアで拡張作成に失敗します。リストアより前に入れておきます。

# 16版のpg_repackを削除(残っていれば)
sudo dnf remove -y pg_repack_16 2>/dev/null

# 17版のpg_repackをインストールできませんでした(2026/05/20)
# 後述のビルドからインストールまでを実施してください。
#  sudo dnf install -y pg_repack_17
#  入らない場合は利用可能なパッケージ名を探す
#  sudo dnf search pg_repack

pg_repack はシリーズ#1の環境に後から追加した拡張です(/usr/pgsql-16/ 配下にpg_repack専用のファイルが置かれているのはこのためで、PostgreSQL本体とは無関係)。パッケージ名はリポジトリにより pg_repack_17pg_repack17 など差があるため、見つからなければ dnf search pg_repack で確認してください。どうしても17対応版が用意できない場合は、後述の「pg_repackのPostgreSQL17での対応」や「pg_repackが17で入手できない場合」を参照してください。

4.5 17の初期化

シリーズ#1は標準リポジトリの初期インストール(postgresql-setup initdb)でした。同じやり方で17を初期化します。

# 17のデータディレクトリを初期化
sudo postgresql-setup --initdb

# サービス起動・自動起動設定
sudo systemctl start postgresql
sudo systemctl enable postgresql

# 17として上がっているか確認
sudo -u postgres psql -c "SELECT version();"

シリーズ#1は標準リポジトリの初期インストールのままで、ロケールやエンコーディングを明示指定していません。本記事も同じく postgresql-setup --initdb のデフォルトで初期化します。16と17で初期化条件が揃うため、この点での不一致は起きません。

4.6 リストア

退避しておいた圧縮ダンプを、解凍しながら17へ流し込みます。

sudo -u postgres bash -c "gunzip -c /var/backups/pg/dump_all*.sql.gz | psql"

一度ファイルに解凍してから流すと、また /tmp や容量を気にすることになります。gunzip -c ... | psql とパイプで直接流し込めば、巨大な中間ファイルを作らずに済みます。

pg_repackについて:4.4で17版の pg_repack を導入していれば、ダンプ内の CREATE EXTENSION pg_repack はそのまま通ります。導入していないと、その行で extension "pg_repack" is not available というエラーが出ます。ただし pg_repack はテーブルを再編成するための運用ツールであり、データ本体には含まれません。そのため、このエラーが出てもpgbench_test等のテーブルやデータ自体は問題なくリストアされます。エラーが出た場合は4.4に戻って17版を入れてから、pg_repack 拡張だけ後述5.2の手順で作成すれば追いつけます。

エラーなく終われば、pgbench_test データベースを含むクラスタが17上に再構築されています。

# データベース一覧で pgbench_test があるか確認
sudo -u postgres psql -c "\l"

# シリーズ#1のテーブルが戻っているか確認
sudo -u postgres psql -d pgbench_test -c "\dt"

4.7 設定の移し替え

3.3で控えた16の設定値を見ながら、17の postgresql.conf に必要な変更を再適用します。ファイルを丸ごと上書きしない でください(17で意味が変わったパラメータがあるため、差分を見て手で移すのが安全です)。

# 16と17の設定差分を確認
sudo diff /var/backups/pg/postgresql.conf.16.bak /var/lib/pgsql/data/postgresql.conf | less

# 差分が多数出てくるので、下記表を参考に主要な値を変更してください。
sudo cp /var/lib/pgsql/data/postgresql.conf /var/backups/pg/postgresql.conf.17.bak
sudo cp /var/lib/pgsql/data/pg_hba.conf     /var/backups/pg/pg_hba.conf.17.bak

pg_stat_statementsのみあとでインストールを別途実施します。

パラメータ デフォルト値 記事で使用した値 カテゴリ 出典記事
shared_buffers 128MB 512MB / 8MB メモリ #3 postgresql.conf / #4 チェックポインタ
work_mem 4MB 64MB / 128MB メモリ #3 postgresql.conf
max_connections 100 400 接続 #3 postgresql.conf
checkpoint_timeout 5min 30s(劣化用)/ 15min(改善用) チェックポイント #4 チェックポインタ
checkpoint_completion_target 0.9 0.001(劣化用)/ 0.9(改善用) チェックポイント #4 チェックポインタ
max_wal_size 1GB 126MB(劣化用)/ 4GB(改善用) WAL #4 チェックポインタ
bgwriter_delay 200ms 10s(劣化用) / 100ms(改善用) bgwriter #4 チェックポインタ
bgwriter_lru_maxpages 100 0(劣化用) / 300(改善用) bgwriter #4 チェックポインタ
bgwriter_lru_multiplier 2.0 2(参考掲載) bgwriter #4 チェックポインタ
log_checkpoints off on ログ #4 チェックポインタ
shared_preload_libraries (空) 'pg_stat_statements' 拡張機能 #6 pg_stat_statements
# 適切な値に変更
sudo vi /var/lib/pgsql/data/postgresql.conf 

# 値を比較
sudo diff /var/backups/pg/postgresql.conf.17.bak /var/lib/pgsql/data/postgresql.conf | less

設定変更後はリロードまたは再起動します。

# サービス再起動
sudo systemctl restart postgresql
# サービス状況確認
sudo systemctl status postgresql

5. 事後作業(共通)

5.1 統計情報の再作成(推奨)

dump/restoreではリストア時に統計が作り直されますが、念のため明示的に ANALYZE を流すと、シリーズ#5(EXPLAIN ANALYZE)で見たような統計起因の遅いプランを避けられます。

    sudo -u postgres vacuumdb --all --analyze-in-stages

--analyze-in-stages は粗い統計を素早く作り、段階的に精度を上げます。

5.2 拡張の入れ直し

3.1で確認した通り、この環境の拡張は5つです。plpgsql は標準同梱で対応不要、残り4つを17で揃えます。pg_prewarmpg_stat_statementspgstattuplepostgresql17-contrib(4.4で導入済み)でカバーされ、pg_repack だけ別パッケージです。

# preload設定の確認(16から手で移していなければ未設定のはず)
sudo -u postgres psql -c "SHOW shared_preload_libraries;"

# shared_preload_libraries = 'pg_stat_statements'
sudo vi /var/lib/pgsql/data/postgresql.conf 

# contrib系の拡張を17向けに更新
sudo -u postgres psql -d pgbench_test -c "ALTER EXTENSION pg_stat_statements UPDATE;"
sudo -u postgres psql -d pgbench_test -c "ALTER EXTENSION pgstattuple UPDATE;"
sudo -u postgres psql -d pgbench_test -c "ALTER EXTENSION pg_prewarm UPDATE;"

pg_stat_statementspg_prewarmshared_preload_libraries に載せて再起動しないと機能しません。4.7で16の設定を移していないと未設定のままです。シリーズ#6(pg_stat_statements)等を17で追試するなら、ここで設定して再起動が必要です。

拡張が正しく入ったかの最終確認

3.1で控えた一覧と突き合わせ、すべての拡張が17側にも揃っているか確認します。

# 3.1と同じコマンドで拡張一覧を再取得し、5つ揃っているか照合
sudo -u postgres psql -d pgbench_test -Atc \
  "SELECT extname, extversion FROM pg_extension ORDER BY extname;"

pg_repackのPostgreSQL17での対応(2026/05/20時点)

# pg_repackは存在しない
# ソースからビルド、インストールを実施

# 競合する16版のdevelを削除
sudo dnf remove -y postgresql16-private-devel

# 必要なパッケージを一括インストール
sudo dnf install -y \
    postgresql17-server-devel \
    postgresql17-private-devel \
    postgresql17-static \
    lz4-devel \
    zlib-devel \
    readline-devel

# pg_configの確認
/usr/bin/pg_config --version
# → PostgreSQL 17.x と表示されればOK

# ソースの取得
wget https://github.com/reorg/pg_repack/archive/refs/tags/ver_1.5.3.tar.gz -O pg_repack-1.5.3.tar.gz
tar xzf pg_repack-1.5.3.tar.gz
cd pg_repack-ver_1.5.3

# ソースのビルド
make PG_CONFIG=/usr/bin/pg_config
sudo make install PG_CONFIG=/usr/bin/pg_config

# pg_repackはTCP接続(127.0.0.1)を使うため、ident認証ではなくmd5認証が必要
# 認証方式変更
sudo sed -i 's/host    all             all             127.0.0.1\/32            ident/host    all             all             127.0.0.1\/32            md5/' /var/lib/pgsql/data/pg_hba.conf
sudo systemctl restart postgresql

# DBへの拡張機能登録
psql -U postgres -h 127.0.0.1 -d pgbench_test -c "CREATE EXTENSION IF NOT EXISTS pg_repack;"

# バージョン確認
pg_repack --version

# ドライラン
# パスワードを求められるのでpostgresユーザのパスワードを入力
pg_repack -h 127.0.0.1 -U postgres -d pgbench_test --dry-run -t pgbench_accounts

# テーブル再編成
pg_repack -h 127.0.0.1 -U postgres -d pgbench_test -t pgbench_accounts

pg_repackが17で簡単に入手できない場合
リポジトリに17対応の pg_repack がまだ無いケースがあります(新メジャー直後は対応が遅れることがある)。その場合の選択肢は3つです。(1) pg_repack を諦めて17では使わない(テーブル再編成は VACUUM FULLpg_repack 無しのメンテで代替)。(2) 17対応版が出るまでアップグレードを待つ。(3) ソースから17向けにビルドする。シリーズの検証目的なら(1)で十分で、pg_repackが無くてもpgbenchの計測やパラメータ検証には支障ありません。「拡張の対応状況がメジャーアップグレードの実務上のボトルネックになる」というのは、本番運用でも発生しそうな学びです。

5.3 後片付け

17で問題なく動くことを十分確認したら、退避物を片付けます。動作確認が完全に終わるまでは消さないこと。

# 退避していた16データと一時ファイル
sudo rm -rf /var/lib/pgsql/data_16_old
sudo rm -f /var/backups/pg/dump_all*.sql.gz /var/backups/pg/pgsql_data_16_backup.tar.gz

6. (参考)それでもpg_upgradeを使いたい場合

2章で書いた通り、標準リポジトリのままではpg_upgradeは素直に使えません。それでも使うなら、おおまかに次のどちらかになります。

アプローチ 概要 難易度
PGDGリポジトリへ移行 17をPGDGで導入し /usr/pgsql-17/ を確保。新旧パスが分離されpg_upgradeが本来の形で使える 中(環境構築の作り直しに近い)
17を一時的に別パスへ手動配置 17バイナリと17用データを標準外のパスに用意し、フルパスでpg_upgradeを実行 高(標準運用から外れ保守性が落ちる)

検証環境かつpgbenchの小規模データという前提では、この手間に見合うメリットは小さい と判断しています。pg_upgradeの真価(データ量に依存しない高速移行)が効くのは大規模DBであり、今回の規模ではdump/restoreの所要時間は実用上問題になりません。

7. つまずきポイント集

症状 原因 対処
16と17を同時に入れたら競合した 標準リポは同一データディレクトリ/サービス名 共存させず「16削除→17導入」で進める
リストアでロール関連エラー pg_dump(単一DB)だけ取得しロールが無い pg_dumpall で取り直す
起動はするが特定クエリが激遅 統計が未作成 vacuumdb --all --analyze-in-stages
拡張が見つからないエラー 17側で拡張未作成/preload未設定 postgresql17-contrib 導入+設定移し+ ALTER EXTENSION ... UPDATE
extension "pg_repack" is not available pg_repackはcontrib外。17版未導入 4.4で pg_repack_17 を導入してから拡張作成。データ本体は無事なので慌てない
17版pg_repackがリポジトリに無い 新メジャー直後で未対応 5.2コラム参照。検証目的ならpg_repack無しで進めて問題ない
pg_dumpallNo space left on device /tmp がtmpfs(メモリ上)で数百MBしかない ダンプ先をルートFS上にし gzip 圧縮。3.2参照
設定を丸ごと上書きしたら起動しない 17で非互換になったパラメータ 16設定はdiffで見て手で移す。バックアップから戻す
data_16_old を消してしまい戻せない 後片付けを早まった 3.2のダンプ/4.3のtarアーカイブから復旧
pg_config が壊れたシンボリックリンク postgresql17-server-devel が未インストール postgresql17-server-devel を追加インストール
libpgcommon / libpgport が見つからない postgresql17-static が未インストール postgresql17-static を追加インストール
Peer authentication failed pg_repackはUnixソケット経由では認証できない pg_hba.conf の 127.0.0.1 をmd5に変更

8. もっと深く学びたい方へ

ページ URL
アップグレード全般 https://www.postgresql.jp/docs/17/upgrading.html
pg_upgrade https://www.postgresql.jp/docs/17/pgupgrade.html
pg_dumpall https://www.postgresql.jp/docs/17/app-pg-dumpall.html
PostgreSQL 17 リリースノート https://www.postgresql.org/docs/17/release-17.html

9. おわりに

メジャーバージョンアップというと身構えますが、ポイントは2つだと思っています。1つは 取り返しのつかない操作の前にバックアップを二重化する こと(本記事では論理ダンプとデータディレクトリのtarアーカイブ)。もう1つは 自分の環境の制約を正しく知る ことです。

シリーズ#1がAmazon Linux 2023の標準リポジトリを選んでいるからこそ、「pg_upgradeが教科書通りには使えない」という現実にぶつかります。これは失敗ではなく、環境の特性です。標準リポジトリなら素直にdump/restore、pg_upgradeの高速移行が本当に欲しくなったらPGDGへ──この判断軸を、検証環境で一度自分の手で通しておくと、本番で迷いません。

そしてもう1つ、今回の検証で浮き彫りになったのが 拡張の対応状況がアップグレードの実務上のボトルネックになる という点です。pg_repack のようなcontrib外の拡張は、PostgreSQL本体が17対応していても、拡張側のパッケージが追いつくまで移行を完了できません。本番でメジャーアップグレードを計画するときは、「使っている全拡張の新バージョン対応状況」を最初に確認する──これは検証環境で一度ハマってみないと体感しにくい、実務で本当に効く教訓です。

加えて、/tmp がtmpfs(メモリ上)でダンプが容量不足で死ぬ、という事故も実際に踏みました。これも机上では気づきにくく、手を動かして初めて分かる種類の落とし穴です。バックアップの出力先とサイズは、作業前に必ず実物で確認する──地味ですが、これがメジャーアップグレードを安全に回す土台だと思います。

なお、PostgreSQL16から、PostgreSQL17でpgbenchのTPSやレイテンシが実際どう変わるかは、別記事で実測する予定です。本記事でPostgreSQL17環境が手に入ったので、次はその上で数字を見ていきます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?