PostgreSQL のモード別終了方法

postgresql
3 年位開発環境で放置プレーされていた PostgreSQL を終了させようとしても、プロセスが終了してくれなかったので、PostgreSQL を終了させる方法をメモ。

$ sudo /etc/init.d/postgresql stop
waiting for postmaster to shutdown ............................................................... failed

Shutdown Mode

postgres は $ pg_ctl -D datadir stop でサーバを終了でき、

  • smart
  • fast
  • immediate

の3種類の終了モードがある。

$ pg_ctl -D datadir stop -m mode_name

smart mode

確立ずみセッションの終了とオンラインバックアップの完了を持って、サーバを終了する。
デフォルト。

コマンド実行後は新規接続を受け付けなくなる。

fast mode

各プロセスにシグナル SIGINT を送信する。
セッションを強制終了し、トランザクションをロールバックする。
オンラインバックアップも終了させ、サーバを終了する。

今回はこのモードで終了させた。

immediate mode

各プロセスにシグナル SIGQUIT を送信する。
各プロセスは終了処理を行わないまま終了するため、次回起動時にリカバリ処理が走る。

SIGNAL と終了モードの対応関係

各終了モードは 以下のシグナルと対応している。

  • smart => SIGTERM
  • fast => SIGINT
  • immediate => SIGQUIT

したがって pg_ctl で終了モードを指定する代わりに、kill でシグナル送信しても、同じ結果を得られる。

$ kill -INT `head -1 /usr/local/pgsql/data/postmaster.pid`

smart モードでプロセスが終了しなかったからと、$ kill -TERM pid をやっても、内部的には同じ処理をしている。

なお、Windows のように kill コマンドが無い環境のために、次のようにして pg_ctl 経由でもシグナル送信できる。

$ /usr/lib/postgresql/9.1/bin/pg_ctl -D /var/lib/postgresql/9.1/main kill TERM 22267

Ubuntu の場合

Ubuntu の /etc/init.d/postgresql では、次の 2 通りで終了できる。

$ sudo /etc/init.d/postgresql stop
$ sudo /etc/init.d/postgresql stop --force

前者は smart モードで終了させる。
後者は fast(SIGINT) -> immediate(SIGTEM) -> SIGKILL と順次試しながら、成功するまでエスカレーションしていく。
具体的には、Perl プログラム /usr/bin/pg_ctlcluster で次のようになっている。

sub stop {
    stop_check_pid_file;
    my $result = 1;

    if ($force) {
        if (!fork()) {
            close STDOUT;
            exec $pg_ctl, '-D', $info{'pgdata'}, '-s', '-w', '-m', 'fast', @pg_ctl_opts_from_cli, 'stop';
        } else {
            wait;
        $result = $? >> 8;
        }

        # try harder if "fast" mode does not work
        if (-f $info{'pgdata'}.'/postmaster.pid') {
            print "(does not shutdown gracefully, now stopping immediately)\n";
        $result = system $pg_ctl, '-D', $info{'pgdata'}, '-s', '-w', '-m', 'immediate', @pg_ctl_opts_from_cli, 'stop';
        }

        # if that still not helps, use the big hammer
        if (-f $info{'pgdata'}.'/postmaster.pid') {
            print "(does not shutdown, killing the process)";
            $pid = get_running_pid $info{'pgdata'}.'/postmaster.pid';
            kill (9, $pid) if $pid;
        $result = 0;
        }
    }

ログ出力

各モードで終了されたときの、postgres のログ出力を確認。

smart mode

2013-03-11 22:35:49 JST LOG:  received smart shutdown request
2013-03-11 22:35:49 JST LOG:  autovacuum launcher shutting down
2013-03-11 22:35:49 JST LOG:  shutting down
2013-03-11 22:35:49 JST LOG:  database system is shut down

fast mode

2013-03-11 22:50:36 JST LOG:  received fast shutdown request
2013-03-11 22:50:36 JST LOG:  aborting any active transactions
2013-03-11 22:50:36 JST LOG:  autovacuum launcher shutting down
2013-03-11 22:50:36 JST LOG:  shutting down
2013-03-11 22:50:37 JST LOG:  database system is shut down

immediate mode

2013-03-11 22:51:45 JST LOG:  received immediate shutdown request
2013-03-11 22:51:45 JST WARNING:  terminating connection because of crash of another server process
2013-03-11 22:51:45 JST DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
2013-03-11 22:51:45 JST HINT:  In a moment you should be able to reconnect to the database and repeat your command.

References

Advertisements
Tagged with: , ,
Posted in database

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives

Error: Twitter did not respond. Please wait a few minutes and refresh this page.

%d bloggers like this: