2009-06-30 18 views
21

phpPgAdminインターフェイスを使用して大規模なPostgreSQLテーブルでupdate文を実行しました。これはあまりにも長く走ったのでタイムアウトしました。可能なPostgres行ロックを解放するには?

これで、そのテーブルの一部の行を更新できるようになりました。一部の行を更新しようとするとハングします。

ローはロックされていますか?これらの行を更新するにはどうすればよいですか?

答えて

20

実行中のPostgreSQLのバージョンは何ですか?以下は8.1.8以降を前提としています(以前のバージョンにも当てはまるかもしれませんが、わかりません)。

私はあなたがphpPgAdminがタイムアウトしたことを意味すると推測します。PostgreSQLのバックエンドは、クエリ/更新を完了するのにかかる時間がかかります。その場合、元のセッションがまだ有効で、UPDATEクエリがまだ実行中である可能性があります。いくつかの行が表示されます

ps auxwww|grep ^postgres 

:私は、セッションがまだ生きているかどうかを確認するために、PostgreSQLサーバ・プロセスをホストマシン上で(chapter 24 of the PostgreSQL docsから取られた)次のクエリを実行している示唆1 postmasterマスター・プロセスのために、と1つは "writer"、 "stats buffer"、 "stats collector"の各プロセスです。残りの行は、DB接続を処理するプロセス用です。これらの行には、ユーザー名とデータベース名が含まれます。

うまくいけば、元のUPDATEを実行したセッションがまだぶら下がっているかどうかを確認できます。理論的にはあなたがシステムビューpg_stat_activityからINGのSELECTすることにより、より詳細な情報を見つけることができますが、デフォルトではPostgreSQLは、(例えばcurrent_queryquery_startなど)最も有用なフィールドを移入するように設定されていません。これを将来的に有効にする方法については、第24章を参照してください。

セッションがまだ表示されている場合は、それを強制終了します。プロセスを実行するユーザー(通常はpostgres)またはrootとしてログインする必要があります。サーバーを自分で実行しない場合は、DBAに依頼してください。

もう1つ:テーブルの行を更新するために、PostgreSQLはロックの使用を避けます。代わりに、トランザクションをコミットするときに「現行バージョン」となるDBの新しい「バージョン」を作成するすべての書込みトランザクションを可能にします。ただし、他のトランザクションによって行われた更新と競合しない場合に限ります。だから私はあなたが見ている "ぶら下がっ"が何か他のものによって引き起こされていると思っています - でも、私はよくわかりません。 (あなたがDBを含むディスクパーティションがいっぱいであるかどうかのような、明白な事を確認しました?)

+0

優秀、これはうまくいきました、ありがとうございます。問題の原因となっていたプロセスを強制終了すると、ロックが解放されるのを待っていた他のプロセスが実行できることに注意してください。これはいくつかのさらなる問題を引き起こしました。私はps auxwww | grep^postgresを実行して最初の問題プロセスを終了する前に、「待機中」と表示されたプロセスを強制終了するべきでした。 – Liam

+0

私は助けることができてうれしいよ:) –

+2

"セッションがまだ見えたら、それを殺す。" - 初心者の方には、 'postgres 15398 ...トランザクション中にアイドル状態なのか'何かを見て、パテで 'kill 15398'と入力してください。 – Noumenon

0

私はPostResqlを使ったことはありませんが、他の人に似ていると、接続を終了する/ロックを保持しているトランザクションを終了する必要があると言えます。

46

それはロックを確認することが可能です。ここで

は直接としてpg_locksを使用するよりも、それは少し楽にするための図である。

CREATE OR REPLACE VIEW public.active_locks AS 
SELECT t.schemaname, 
    t.relname, 
    l.locktype, 
    l.page, 
    l.virtualtransaction, 
    l.pid, 
    l.mode, 
    l.granted 
    FROM pg_locks l 
    JOIN pg_stat_all_tables t ON l.relation = t.relid 
    WHERE t.schemaname <> 'pg_toast'::name AND t.schemaname <> 'pg_catalog'::name 
    ORDER BY t.schemaname, t.relname; 

次に、あなただけのビューから選択:

SELECT * FROM active_locks; 

し、それを殺す:

SELECT pg_cancel_backend('%pid%'); 

その他のソリューション: http://wiki.postgresql.org/wiki/Lock_Monitoring

+2

Postgresに 'active_locks'という名前のビューまたはテーブルはありません。おそらく 'pg_locks'を意味しますか? –

+0

あなたは正しいです、我々のデータベースにカスタムビューがありました、私は答えを編集しました。 – Chris

+0

私の場合は、あなたの 'pg_cancel_backend'をここにqeuryと組み合わせて:http://stackoverflow.com/a/10317371/301277すべての"忘れた "ロックを削除することができました。ありがとう! –

関連する問題