2009-06-30 13 views
21

Ho eseguito un'istruzione di aggiornamento su una tabella PostgreSQL di grandi dimensioni tramite l'interfaccia phpPgAdmin. Questo è scaduto per troppo tempo.Come rilasciare possibili blocchi di riga Postgres?

Ora posso aggiornare alcune righe da quella tabella ma non tutte. Cercando di aggiornare alcune righe si bloccherà.

Le righe sono bloccate? Come posso consentire l'aggiornamento di queste righe?

risposta

20

Quale versione di PostgreSQL è in esecuzione? Quanto segue assume 8.1.8 o versioni successive (potrebbe valere anche per le versioni precedenti, non lo so).

Presumo che si intenda il timeout di phpPgAdmin - il backend PostgreSQL impiegherà tutto il tempo necessario per completare una query/aggiornamento. In tal caso, è possibile che la sessione originale sia ancora attiva e che la query UPDATE sia ancora in esecuzione. Suggerisco di eseguire il seguente query (tratto da chapter 24 of the PostgreSQL docs) sulla macchina che ospita il processo server PostgreSQL, per vedere se la sessione è ancora vivo:

ps auxwww|grep ^postgres 

Diverse righe dovrebbero apparire: 1 per il processo postmaster padrone, e 1 ciascuno per i processi "writer", "stats buffer" e "stats collector". Le eventuali righe rimanenti si riferiscono ai processi che servono connessioni DB. Queste righe conterranno il nome utente e il nome del database.

Speriamo che da questo sia possibile vedere se la sessione in cui è stato eseguito l'UPDATE originale è ancora in giro. Sebbene in teoria si possano trovare informazioni più dettagliate tramitedalla vista di sistema pg_stat_activity, per impostazione predefinita PostgreSQL non è impostato per popolare i campi più utili (come current_query e query_start). Vedi il capitolo 24 per come abilitare questo in futuro.

Se vedi che la sessione è ancora lì, uccidila. Dovrai effettuare l'accesso come utente che esegue il processo (solitamente postgres) o root per farlo - se non esegui il server da solo, chiedi al tuo DBA di farlo per te.

Un'altra cosa: per l'aggiornamento delle righe in una tabella, PostgreSQL evita l'utilizzo di blocchi. Invece, consente a ogni transazione di scrittura di creare una nuova "versione" del DB, che diventa la "versione corrente" al momento del commit della transazione, purché non sia in conflitto con gli aggiornamenti effettuati nel frattempo da altre transazioni. Quindi sospetto che l'impiccagione che stai vedendo sia causata da qualcos'altro, anche se, non ne sono sicuro. (Avete verificato le cose ovvie, come se la partizione del disco contenente il DB sia piena?)

+0

Eccellente, questo ha funzionato, grazie. Si noti che quando ho ucciso il processo che stava causando il problema, questo ha permesso l'esecuzione di altri processi che stavano aspettando il rilascio del blocco. Ciò ha causato alcuni ulteriori problemi. Avrei dovuto uccidere i processi contrassegnati "WAITING" quando ho eseguito ps auxwww | grep^postgres prima di uccidere il primo processo problematico. – Liam

+0

Felice di poter aiutare :) –

+2

"Se vedi che la sessione è ancora lì, uccidila." - Per i neofiti, guarda dove dice "postgres 15398 ... inattivo nella transazione" o qualsiasi altra cosa e digita "uccidi 15398" in Putty. – Noumenon

0

Non ho mai lavorato con PostreSql ma se è simile ad altri, direi che devi interrompere la connessione/terminare la transazione che tiene i blocchi.

46

È possibile vedere le serrature.

Qui è una vista per renderlo un po 'più facile che usare pg_locks direttamente:

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; 

Poi basta selezionare dal punto di vista:

SELECT * FROM active_locks; 

e uccidere con:

SELECT pg_cancel_backend('%pid%'); 

Altre soluzioni: http://wiki.postgresql.org/wiki/Lock_Monitoring

+2

Non c'è nessuna vista o tabella con il nome 'active_locks' in Postgres. Vuoi forse dire "pg_locks"? –

+0

Hai ragione, c'era una vista personalizzata nel nostro database, ho modificato la risposta. – Chris

+0

Nel mio caso, il tuo 'pg_cancel_backend' in combinazione con il qeury qui: http://stackoverflow.com/a/10317371/301277 mi ha permesso di rimuovere tutte le serrature" dimenticate ". Grazie! –

Problemi correlati