2012-09-25 5 views
2

AFAIK, PostgreSQL 8.3 ne prend pas en charge le délai d'expiration des transactions. J'ai lu sur le soutien de cette fonctionnalité à l'avenir et il y a une discussion à ce sujet. Cependant, pour des raisons spécifiques, j'ai besoin d'une solution à ce problème. Donc, ce que je faisais est un script qui exécute périodiquement:Solution de contournement de délai de transaction pour PostgreSQL

1) Sur la base de serrures et de l'activité, la requête afin de récupérer processID des transactions qui prend trop de temps, et de garder le plus ancien (trxTimeOut.sql):

SELECT procpid 
FROM 
(
    SELECT DISTINCT age(now(), query_start) AS age, procpid 
    FROM pg_stat_activity, pg_locks 
    WHERE pg_locks.pid = pg_stat_activity.procpid 
) AS foo 
WHERE age > '30 seconds' 
ORDER BY age DESC 
LIMIT 1 

2) sur la base de cette requête, tuer le processus correspondant (trxTimeOut.sh):

psql -h localhost -U postgres -t -d test_database -f trxTimeOut.sql | xargs kill 

Bien que je l'ai testé et semble fonctionner, je voulez-vous savoir si c'est une approche acceptable ou devrais-je en envisager une autre? PostgreSQL 8.3 prend en charge la temporisation au niveau de l'instruction.

+0

est une mise à niveau vers au moins la version 8.4 une option? Si c'est le cas, vous pouvez utiliser pg_terminate_backend() pour fermer les connexions ouvertes. –

+0

Merci pour votre réponse. Malheureusement, je ne peux pas prendre cette mise à jour pour acquis (ne dépend pas de moi). Quoi qu'il en soit, pg_terminate_backend() serait seulement un meilleur moyen de mettre fin à la connexion que la commande kill, non? Je veux dire, la solution query + kill (ou terminer) est relativement acceptable? –

Répondre

3

Bien qu'il ne s'agisse pas exactement d'un délai d'expiration de transaction car il ne compte pas le temps passé dans les déclarations précédentes de la même transaction, il est généralement suffisant pour éviter qu'un client ne reste coincé dans une requête.

Pour interrompre automatiquement la transaction si une déclaration prend plus de 10 secondes:

SET statement_timeout=10000; 
+0

Merci, mais le problème est un peu plus complexe. Si une application client. se bloque pour une raison quelconque (lié à un événement Java Swing, mais pas lié à une instruction trop longue), cela pourrait éventuellement bloquer d'autres clients puisque le premier client a des verrous accordés (dans la transaction non validée/annulée) que le deuxième est en attente d'accès. Le script tue la première transaction parce que cela prend trop de temps, peu importe la source du problème (permettant ainsi au second client de continuer). statement_timeout n'abandonnera que la transaction du deuxième client (à cause des verrous) –

+1

'statement_timeout' n'indique pas l'état" inactif dans la transaction ", ce qui peut empêcher la relecture du journal. Il y a des cas très concrets où cette réponse n'est pas assez bonne. –

Questions connexes