2017-05-05 1 views
1

Quand j'exécuter:lors de l'utilisation Hibernate, Postgres et Guice Fournisseur

select * from pg_stat_activity where state ~ 'idle in transact' 

Je reçois nombre inapproprié de lignes avec l'état "inactif dans la transaction. Certains d'entre eux tournent au ralenti pendant quelques jours. La plupart d'entre eux, sont les mêmes requête simple select qui sont exécutés d'une classe de service (Mise en veille prolongée 5.1.0.Final, Guice 4.1.0):

public class FirebaseServiceImpl implements FirebaseService { 

    @Inject 
    private Provider<FirebaseKeyDAO> firebaseKeyDAO; 

    @Override 
    public void sendNotification(User recipient) { 

     List<FirebaseKey> firebaseKeys = firebaseKeyDAO.get().findByUserId(recipient.getId()); 

     final ExecutorService notificationsPool = Executors.newFixedThreadPool(3); 

     for (FirebaseKey firebaseKey : firebaseKeys) 
      notificationsPool.execute(new Runnable() { 

       @Override 
       public void run() { 
        sendNotification(new FirebaseNotification(firebaseKey.getFirebaseKey(), "example"); 
       } 
     }); 

     notificationsPool.shutdown(); 
    } 
} 

méthode DAO:

@Override 
@SuppressWarnings("unchecked") 
public List<FirebaseKey> findByUserId(Long userId) { 
    Criteria criteria = getSession().createCriteria(type); 
    criteria.add(Restrictions.eq("userId", userId)); 
    return criteria.list(); 
} 

Pourquoi est-ce ça arrive? Comment éviter cela?

MISE À JOUR

transactions ne sont pas commited lorsque j'utilise Guice fournisseur exampleDAO.get() dans un thread séparé:

@Inject 
Provider<ExampleDAO> exampleDAO; 

Répondre

2

Il se produit généralement lorsque vous utilisez pgbouncer ou tout autre gestionnaire Pooler/session qui utilise pool_mode = transaction. Par exemple, lorsque le client ouvre une transaction et la conserve, ne s'engage ni ne recule. Vérifiez si vous voyez DISCARD ALL dans la colonne de requête - si cela est le cas, because pooler doit ignorer les plans de sessions partagés, les séquences, les déclarations de désallocation etc. pour éviter de mélanger ceux pour différentes sessions dans le pool.

D'autre part une opération "normale" donne même idle in transaction, par exemple:

2>select now(),pg_backend_pid(); 
       now    | pg_backend_pid 
----------------------------------+---------------- 
2017-05-05 16:53:01.867444+05:30 |   26500 
(1 row) 

si nous vérifions son état, nous voyons orthodoxe idle:

t=# select query,state from pg_stat_activity where pid = 26500; 
      query    | state 
--------------------------------+------- 
select now(),pg_backend_pid(); | idle 
(1 row) 

maintenant nous commençons transaction sur session 2 >: 2> commencer; BEGIN

2>select now(),pg_backend_pid(); 
       now    | pg_backend_pid 
----------------------------------+---------------- 
2017-05-05 16:54:15.856306+05:30 |   26500 
(1 row) 

et vérifier pg_stat_statements Gain:

t=# select query,state from pg_stat_activity where pid = 26500; 
      query    |  state 
--------------------------------+--------------------- 
select now(),pg_backend_pid(); | idle in transaction 
(1 row) 

Il restera ainsi tant que le délai de déclaration ou à la fin de la transaction:

2>end; 
COMMIT 
t=# select query,state from pg_stat_activity where pid = 26500; 
query | state 
-------+------- 
end; | idle 
(1 row) 

Il est assez fréquent et ok avoir il. Si vous voulez éviter les sessions connectées, vous devez déconnecter le client. Mais la connexion dans postgres est chère, donc généralement les gens essayent de réutiliser les connexions existantes avec pool, et donc ces états apparaissent dans pg_stat_activity

+0

Parfois, j'ai beaucoup de requêtes longues 'COMMIT' avec l'état 'idle'. Pourquoi cela arrive-t-il? Cela vaut-il la peine d'exécuter 'echo never>/sys/kernel/mm/redhat_transparent_hugepage/enabled' comme il est mentionné sur https://dba.stackexchange.com/questions/32890/postgresql-pg-stat-activity-shows-commit? – Justas

+0

inactif signifie que la connexion persiste à ne rien faire après validation. colonne de requête change lorsque la requête change - la dernière requête exécutée est affichée ... –

+0

Si l'application atteint la limite de hibernate.c3p0.max_size avec des validations d'inactivité, elle cesse de fonctionner avec DB. – Justas